@wirecat/whatsapp-cli 0.0.0-stage → 0.2.0
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/LICENSE +204 -0
- package/README.md +401 -2
- package/dist/adapter/adapter.d.ts +13 -0
- package/dist/adapter/adapter.d.ts.map +1 -0
- package/dist/adapter/adapter.js +554 -0
- package/dist/adapter/adapter.js.map +1 -0
- package/dist/adapter/channels.d.ts +43 -0
- package/dist/adapter/channels.d.ts.map +1 -0
- package/dist/adapter/channels.js +100 -0
- package/dist/adapter/channels.js.map +1 -0
- package/dist/adapter/checks.d.ts +6 -0
- package/dist/adapter/checks.d.ts.map +1 -0
- package/dist/adapter/checks.js +2 -0
- package/dist/adapter/checks.js.map +1 -0
- package/dist/adapter/errors.d.ts +13 -0
- package/dist/adapter/errors.d.ts.map +1 -0
- package/dist/adapter/errors.js +38 -0
- package/dist/adapter/errors.js.map +1 -0
- package/dist/adapter/format-markdown.d.ts +8 -0
- package/dist/adapter/format-markdown.d.ts.map +1 -0
- package/dist/adapter/format-markdown.js +80 -0
- package/dist/adapter/format-markdown.js.map +1 -0
- package/dist/adapter/groups.d.ts +25 -0
- package/dist/adapter/groups.d.ts.map +1 -0
- package/dist/adapter/groups.js +252 -0
- package/dist/adapter/groups.js.map +1 -0
- package/dist/adapter/map.d.ts +23 -0
- package/dist/adapter/map.d.ts.map +1 -0
- package/dist/adapter/map.js +121 -0
- package/dist/adapter/map.js.map +1 -0
- package/dist/adapter/pins.d.ts +11 -0
- package/dist/adapter/pins.d.ts.map +1 -0
- package/dist/adapter/pins.js +10 -0
- package/dist/adapter/pins.js.map +1 -0
- package/dist/adapter/polls.d.ts +21 -0
- package/dist/adapter/polls.d.ts.map +1 -0
- package/dist/adapter/polls.js +103 -0
- package/dist/adapter/polls.js.map +1 -0
- package/dist/adapter/privacy.d.ts +18 -0
- package/dist/adapter/privacy.d.ts.map +1 -0
- package/dist/adapter/privacy.js +94 -0
- package/dist/adapter/privacy.js.map +1 -0
- package/dist/adapter/settings.d.ts +21 -0
- package/dist/adapter/settings.d.ts.map +1 -0
- package/dist/adapter/settings.js +76 -0
- package/dist/adapter/settings.js.map +1 -0
- package/dist/app.d.ts +6 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +16 -0
- package/dist/app.js.map +1 -0
- package/dist/bin/wa.d.ts +3 -0
- package/dist/bin/wa.d.ts.map +1 -0
- package/dist/bin/wa.js +14 -0
- package/dist/bin/wa.js.map +1 -0
- package/dist/commands/session.d.ts +48 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +201 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/setup.d.ts +3 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +140 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +17 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/diagnose.d.ts +77 -0
- package/dist/diagnose.d.ts.map +1 -0
- package/dist/diagnose.js +84 -0
- package/dist/diagnose.js.map +1 -0
- package/dist/engine/channels.d.ts +100 -0
- package/dist/engine/channels.d.ts.map +1 -0
- package/dist/engine/channels.js +29 -0
- package/dist/engine/channels.js.map +1 -0
- package/dist/engine/contract.d.ts +1049 -0
- package/dist/engine/contract.d.ts.map +1 -0
- package/dist/engine/contract.js +353 -0
- package/dist/engine/contract.js.map +1 -0
- package/dist/engine/events.d.ts +9 -0
- package/dist/engine/events.d.ts.map +1 -0
- package/dist/engine/events.js +23 -0
- package/dist/engine/events.js.map +1 -0
- package/dist/engine/go-engine.d.ts +23 -0
- package/dist/engine/go-engine.d.ts.map +1 -0
- package/dist/engine/go-engine.js +227 -0
- package/dist/engine/go-engine.js.map +1 -0
- package/dist/engine/groups.d.ts +171 -0
- package/dist/engine/groups.d.ts.map +1 -0
- package/dist/engine/groups.js +66 -0
- package/dist/engine/groups.js.map +1 -0
- package/dist/engine/privacy.d.ts +33 -0
- package/dist/engine/privacy.d.ts.map +1 -0
- package/dist/engine/privacy.js +23 -0
- package/dist/engine/privacy.js.map +1 -0
- package/dist/engine/settings.d.ts +45 -0
- package/dist/engine/settings.d.ts.map +1 -0
- package/dist/engine/settings.js +34 -0
- package/dist/engine/settings.js.map +1 -0
- package/dist/engine-binary.d.ts +5 -0
- package/dist/engine-binary.d.ts.map +1 -0
- package/dist/engine-binary.js +18 -0
- package/dist/engine-binary.js.map +1 -0
- package/dist/install/postinstall.d.ts +8 -0
- package/dist/install/postinstall.d.ts.map +1 -0
- package/dist/install/postinstall.js +63 -0
- package/dist/install/postinstall.js.map +1 -0
- package/dist/messenger.d.ts +63 -0
- package/dist/messenger.d.ts.map +1 -0
- package/dist/messenger.js +186 -0
- package/dist/messenger.js.map +1 -0
- package/dist/paths.d.ts +5 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +7 -0
- package/dist/paths.js.map +1 -0
- package/dist/program.d.ts +12 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +86 -0
- package/dist/program.js.map +1 -0
- package/dist/reasons.d.ts +4 -0
- package/dist/reasons.d.ts.map +1 -0
- package/dist/reasons.js +21 -0
- package/dist/reasons.js.map +1 -0
- package/dist/update.d.ts +7 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +19 -0
- package/dist/update.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/install/postinstall.mjs +3 -0
- package/install/windows.ps1 +161 -0
- package/package.json +89 -4
- package/skills/whatsapp-cli/SKILL.md +325 -0
package/dist/bin/wa.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { enableCompileCache } from "node:module";
|
|
3
|
+
import { catchCrashes } from "@wirecat/cli-base";
|
|
4
|
+
import { ensureSqlite } from "@wirecat/cli-core/sqlite-runtime";
|
|
5
|
+
import { WA } from "../app.js";
|
|
6
|
+
// Compiling the module files is most of a start; later runs reuse what this one compiled.
|
|
7
|
+
enableCompileCache();
|
|
8
|
+
const stopCatching = catchCrashes({ cli: WA.command, interactive: process.stdout.isTTY === true });
|
|
9
|
+
await ensureSqlite();
|
|
10
|
+
stopCatching();
|
|
11
|
+
// A static import would load the whole program, and its SQLite, before ensureSqlite could swap it.
|
|
12
|
+
const { run } = await import("../program.js");
|
|
13
|
+
process.exitCode = await run(process.argv.slice(2));
|
|
14
|
+
//# sourceMappingURL=wa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wa.js","sourceRoot":"","sources":["../../src/bin/wa.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC/D,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAA;AAE9B,0FAA0F;AAC1F,kBAAkB,EAAE,CAAA;AACpB,MAAM,YAAY,GAAG,YAAY,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC,CAAA;AAClG,MAAM,YAAY,EAAE,CAAA;AACpB,YAAY,EAAE,CAAA;AACd,mGAAmG;AACnG,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;AAC7C,OAAO,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type MessengerContext } from "@wirecat/cli-core/cli";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
/**
|
|
4
|
+
* Shown once, before the code that links the device. It ignores `--quiet` the way the QR code does: it belongs to
|
|
5
|
+
* the prompt the person is answering, and after the link it is too late to read it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const BAN_WARNING: string;
|
|
8
|
+
/** The phone pushes its history right after linking, once; how long to keep receiving it. */
|
|
9
|
+
export declare const HISTORY_WAIT: HistoryWait;
|
|
10
|
+
/** `slowMs`: with nothing pushed by then, say once that the wait goes on, so the silence does not read as a hang. */
|
|
11
|
+
export interface HistoryWait {
|
|
12
|
+
firstMs: number;
|
|
13
|
+
quietMs: number;
|
|
14
|
+
slowMs?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface Received {
|
|
17
|
+
chats: number;
|
|
18
|
+
messages: number;
|
|
19
|
+
people: number;
|
|
20
|
+
}
|
|
21
|
+
export interface StartSessionOptions {
|
|
22
|
+
method: "qr" | "phone";
|
|
23
|
+
/** The command as typed, for the messages that name it. */
|
|
24
|
+
command?: string;
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
/** How far the questions and the QR code sit right, to line up under a setup step. */
|
|
27
|
+
indent?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Ctrl+C, a cancel or --timeout ends the history wait alone, and the command answers with what was kept. A command
|
|
30
|
+
* with steps after the wait calls `endUntilStopped()` when it returns, so those steps get a deadline again.
|
|
31
|
+
*/
|
|
32
|
+
stopEndsWait?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface Session {
|
|
35
|
+
profile: string;
|
|
36
|
+
account: {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string | null;
|
|
39
|
+
};
|
|
40
|
+
alreadyLinked: boolean;
|
|
41
|
+
/** Left out for a device linked before: nothing was pushed, so nothing was counted. */
|
|
42
|
+
received?: Received;
|
|
43
|
+
}
|
|
44
|
+
/** Links the profile's device unless it is linked already, then keeps the history the phone pushes once. */
|
|
45
|
+
export declare const startSession: (command: Command, context: MessengerContext, { method, command: typed, signal, indent: pad, stopEndsWait }: StartSessionOptions) => Promise<Session>;
|
|
46
|
+
export declare const AGENTS_LINK_BY_QR: string;
|
|
47
|
+
export declare const sessionCommand: () => Command;
|
|
48
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"AAIA,OAAO,EAML,KAAK,gBAAgB,EAOtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAY,OAAO,EAAE,MAAM,WAAW,CAAA;AAI7C;;;GAGG;AACH,eAAO,MAAM,WAAW,QAKZ,CAAA;AAEZ,6FAA6F;AAC7F,eAAO,MAAM,YAAY,EAAE,WAAmE,CAAA;AAE9F,qHAAqH;AACrH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf;AAmDD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAA;IACtB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;IAC5C,aAAa,EAAE,OAAO,CAAA;IACtB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACpB;AAED,4GAA4G;AAC5G,eAAO,MAAM,YAAY,YACd,OAAO,WACP,gBAAgB,iEACuE,mBAAmB,KAClH,OAAO,CAAC,OAAO,CA+EjB,CAAA;AA6BD,eAAO,MAAM,iBAAiB,QAKmE,CAAA;AAEjG,eAAO,MAAM,cAAc,eAiD1B,CAAA"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { existsSync, rmSync } from "node:fs";
|
|
2
|
+
import { CliError, indent, singleLine } from "@wirecat/cli-base";
|
|
3
|
+
import { annotate } from "@wirecat/cli-base/commands";
|
|
4
|
+
import { atTerminal, loginQr, readSecret } from "@wirecat/cli-core";
|
|
5
|
+
import { asFirstWord, commandWords, environmentOf, logsInOrOut, messengerContext, printItem, REMOTE_WRITE, refuseCommandName, rootOf, secretInputOf, } from "@wirecat/cli-core/cli";
|
|
6
|
+
import { Argument, Command } from "commander";
|
|
7
|
+
import { linkDevice, WHATSAPP } from "../messenger.js";
|
|
8
|
+
import { privateStore } from "../paths.js";
|
|
9
|
+
/**
|
|
10
|
+
* Shown once, before the code that links the device. It ignores `--quiet` the way the QR code does: it belongs to
|
|
11
|
+
* the prompt the person is answering, and after the link it is too late to read it.
|
|
12
|
+
*/
|
|
13
|
+
export const BAN_WARNING = [
|
|
14
|
+
"Before you link: wa is not an official WhatsApp app, and WhatsApp may ban an account that uses one.",
|
|
15
|
+
"It also bans accounts that send in bulk or write to people who do not know them.",
|
|
16
|
+
"wa writes only when a command asks, sends at most 30 messages an hour by default, and holds every",
|
|
17
|
+
"write when WhatsApp says to slow down or restricts the account. Never send in bulk or to strangers.",
|
|
18
|
+
].join("\n");
|
|
19
|
+
/** The phone pushes its history right after linking, once; how long to keep receiving it. */
|
|
20
|
+
export const HISTORY_WAIT = { firstMs: 120_000, quietMs: 45_000, slowMs: 20_000 };
|
|
21
|
+
/**
|
|
22
|
+
* Saves what the phone pushes until it goes quiet or `signal` aborts. Live messages that arrive meanwhile are saved
|
|
23
|
+
* too, through the same connection.
|
|
24
|
+
*/
|
|
25
|
+
const receiveHistory = async (adapter, wait, onSlow, signal) => {
|
|
26
|
+
const received = { chats: 0, messages: 0, people: 0 };
|
|
27
|
+
const stop = new AbortController();
|
|
28
|
+
const end = () => stop.abort();
|
|
29
|
+
let timer = setTimeout(end, wait.firstMs);
|
|
30
|
+
const slow = wait.slowMs === undefined ? undefined : setTimeout(onSlow, wait.slowMs);
|
|
31
|
+
signal?.addEventListener("abort", end, { once: true });
|
|
32
|
+
try {
|
|
33
|
+
await Promise.all([
|
|
34
|
+
adapter.feed?.((batch) => {
|
|
35
|
+
received.chats += batch.chats?.length ?? 0;
|
|
36
|
+
received.messages += batch.messages?.length ?? 0;
|
|
37
|
+
received.people += batch.people?.length ?? 0;
|
|
38
|
+
clearTimeout(slow);
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
timer = setTimeout(end, wait.quietMs);
|
|
41
|
+
}, stop.signal),
|
|
42
|
+
adapter.watch?.(() => { }, stop.signal),
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
clearTimeout(slow);
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
signal?.removeEventListener("abort", end);
|
|
49
|
+
}
|
|
50
|
+
return received;
|
|
51
|
+
};
|
|
52
|
+
const linkedText = (profile, account, got) => {
|
|
53
|
+
const word = asFirstWord(profile);
|
|
54
|
+
const name = account.name === null ? "you" : singleLine(account.name);
|
|
55
|
+
return [
|
|
56
|
+
got
|
|
57
|
+
? `Linked as ${name} — profile ${profile}.`
|
|
58
|
+
: `Already linked as ${name} — profile ${profile}; nothing was asked. ` +
|
|
59
|
+
`\`wa ${word}session end\` first to link again.`,
|
|
60
|
+
...(got ? [`History: ${got.chats} chats, ${got.messages} messages kept from the phone.`] : []),
|
|
61
|
+
`Next: wa ${word}chats list · wa ${word}server install to keep receiving`,
|
|
62
|
+
].join("\n");
|
|
63
|
+
};
|
|
64
|
+
/** Links the profile's device unless it is linked already, then keeps the history the phone pushes once. */
|
|
65
|
+
export const startSession = async (command, context, { method, command: typed = "wa session start", signal, indent: pad = 0, stopEndsWait = false }) => {
|
|
66
|
+
const input = context.stdin;
|
|
67
|
+
const terminal = atTerminal(input);
|
|
68
|
+
const unanswerable = () => new CliError("validation_error", `${typed} asks questions — run it in a terminal`, {
|
|
69
|
+
reason: "input.required",
|
|
70
|
+
});
|
|
71
|
+
// A device that is linked already asks nothing, so only a profile without one is refused before the engine starts.
|
|
72
|
+
if (!terminal && method === "phone" && !existsSync(privateStore(context.profile, context.env)))
|
|
73
|
+
throw unanswerable();
|
|
74
|
+
const qr = loginQr({
|
|
75
|
+
diagnostic: context.streams.diagnostic,
|
|
76
|
+
note: context.renderer.note,
|
|
77
|
+
indent: pad,
|
|
78
|
+
terminal,
|
|
79
|
+
json: context.format !== "pretty",
|
|
80
|
+
});
|
|
81
|
+
const environment = environmentOf(command);
|
|
82
|
+
const linked = await linkDevice(command, context, {
|
|
83
|
+
method,
|
|
84
|
+
beforeLink: () => {
|
|
85
|
+
signal?.throwIfAborted();
|
|
86
|
+
if (!terminal && method === "phone")
|
|
87
|
+
throw unanswerable();
|
|
88
|
+
context.streams.diagnostic(indent(BAN_WARNING, pad));
|
|
89
|
+
},
|
|
90
|
+
phone: async () => {
|
|
91
|
+
if (!terminal)
|
|
92
|
+
throw new CliError("validation_error", `${typed} phone needs a terminal to ask for the number`, {
|
|
93
|
+
reason: "input.required",
|
|
94
|
+
});
|
|
95
|
+
const number = await readSecret(`${" ".repeat(pad)}phone number, international format: `, {
|
|
96
|
+
...secretInputOf(command),
|
|
97
|
+
echo: true,
|
|
98
|
+
...(signal === undefined ? {} : { signal }),
|
|
99
|
+
});
|
|
100
|
+
// WhatsApp reads the leading digits as the country code, so a number typed without one pairs someone else's.
|
|
101
|
+
if (!number.trim().startsWith("+"))
|
|
102
|
+
throw new CliError("validation_error", "write the phone number with + and the country code, such as +34", {
|
|
103
|
+
param: "phone",
|
|
104
|
+
reason: "input.invalid",
|
|
105
|
+
});
|
|
106
|
+
return number;
|
|
107
|
+
},
|
|
108
|
+
onCode: ({ login, code }) => {
|
|
109
|
+
if (login === "pair") {
|
|
110
|
+
context.renderer.note(`pairing code: ${code}\n` +
|
|
111
|
+
"On the phone: tap the WhatsApp notification, or Settings > Linked devices > Link a device >\n" +
|
|
112
|
+
"Link with phone number instead, and type the code. It expires in about two minutes.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
qr.show(code, "scan in WhatsApp → Settings → Linked devices → Link a device");
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
signal?.throwIfAborted();
|
|
119
|
+
const session = { profile: context.profile, account: linked.account, alreadyLinked: linked.alreadyLinked };
|
|
120
|
+
if (!linked.alreadyLinked) {
|
|
121
|
+
context.renderer.note("receiving history from the phone; keep WhatsApp open on it. Ctrl+C stops — `serve` picks up the rest.");
|
|
122
|
+
const stop = stopEndsWait ? environment.untilStopped?.() : environment.signal;
|
|
123
|
+
const ended = AbortSignal.any([signal, stop].filter((one) => one !== undefined));
|
|
124
|
+
session.received = await context.withMessenger((adapter) => receiveHistory(adapter, environment.historyWait ?? HISTORY_WAIT, () => context.renderer.note("still waiting for the phone's history — keep WhatsApp open on the phone; it can take a minute"), ended), { listen: true });
|
|
125
|
+
}
|
|
126
|
+
return session;
|
|
127
|
+
};
|
|
128
|
+
const end = async (command) => {
|
|
129
|
+
const context = messengerContext(command, WHATSAPP);
|
|
130
|
+
const store = privateStore(context.profile, context.env);
|
|
131
|
+
if (!existsSync(store)) {
|
|
132
|
+
printItem(context, { profile: context.profile, ended: false });
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
let dropped = false;
|
|
136
|
+
try {
|
|
137
|
+
await context.withMessenger((adapter) => adapter.logout());
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
if (error instanceof CliError && error.details.reason === "device.in-use")
|
|
141
|
+
throw new CliError("provider_unavailable", `${error.message} — stop it first (\`wa ${asFirstWord(context.profile)}server stop\` for serve, or Ctrl+C ` +
|
|
142
|
+
"where it runs), then end the session", { ...error.details, sent: false });
|
|
143
|
+
// The phone may have removed the device already; the keys here are then worth nothing, and still go.
|
|
144
|
+
if (!(error instanceof CliError && error.code === "authentication_error"))
|
|
145
|
+
throw error;
|
|
146
|
+
dropped = true;
|
|
147
|
+
}
|
|
148
|
+
for (const suffix of ["", "-wal", "-shm", ".lock"])
|
|
149
|
+
rmSync(`${store}${suffix}`, { force: true });
|
|
150
|
+
if (dropped)
|
|
151
|
+
context.renderer.note("WhatsApp had already dropped this device; deleted its keys here");
|
|
152
|
+
printItem(context, { profile: context.profile, ended: true });
|
|
153
|
+
};
|
|
154
|
+
export const AGENTS_LINK_BY_QR = "Agents: run `wa <profile> session start qr` in the background — it waits for the scan, and a shell tool\n" +
|
|
155
|
+
"shows nothing until it exits. Read its output and paste the QR text block into the chat as a code block,\n" +
|
|
156
|
+
"exactly as printed. WhatsApp renews the code after 60 seconds, then about every 20: paste each new block\n" +
|
|
157
|
+
'at once and say the old one expired. With --json each code is also a stderr line {"event":"qr","qr":{...}}.\n' +
|
|
158
|
+
"Linking is not offered over MCP; an agent with only MCP asks the person to run the command.\n";
|
|
159
|
+
export const sessionCommand = () => {
|
|
160
|
+
// Linking waits for a person, and unlinking removes the owner's device: neither is an agent's call.
|
|
161
|
+
const session = annotate(new Command("session"), { mcp: false }).description("link this profile to WhatsApp as a device, or unlink it");
|
|
162
|
+
annotate(logsInOrOut(session.command("start")), {
|
|
163
|
+
effects: REMOTE_WRITE,
|
|
164
|
+
lifetime: "interactive",
|
|
165
|
+
examples: ["wa personal session start", "wa personal session start phone"],
|
|
166
|
+
})
|
|
167
|
+
.description("link by QR code (default) or a pairing code, then keep the pushed history")
|
|
168
|
+
.addArgument(new Argument("[method]", "how to link").choices(["qr", "phone"]).default("qr"))
|
|
169
|
+
.addHelpText("after", "\nFirst time? Use `wa personal setup` for linking, a check of five chats and an agent skill.\n" +
|
|
170
|
+
"\nqr: scan the code in WhatsApp > Settings > Linked devices > Link a device.\n" +
|
|
171
|
+
"phone: type your number here with + and the country code, then type the code WhatsApp shows here into\n" +
|
|
172
|
+
"the phone.\n" +
|
|
173
|
+
"\nRight after linking, the phone pushes your history once; this command keeps it in the local store\n" +
|
|
174
|
+
"until the phone goes quiet. Then run `wa <profile> server install` to keep receiving.\n" +
|
|
175
|
+
`\n${AGENTS_LINK_BY_QR}`)
|
|
176
|
+
.action(async function (method) {
|
|
177
|
+
const context = messengerContext(this, WHATSAPP);
|
|
178
|
+
refuseCommandName(context.profile, commandWords(rootOf(this)), "wa");
|
|
179
|
+
const session = await startSession(this, context, {
|
|
180
|
+
command: `wa ${asFirstWord(context.profile)}session start`,
|
|
181
|
+
method,
|
|
182
|
+
stopEndsWait: true,
|
|
183
|
+
});
|
|
184
|
+
if (context.format === "pretty")
|
|
185
|
+
context.streams.data(linkedText(context.profile, session.account, session.received));
|
|
186
|
+
else
|
|
187
|
+
printItem(context, {
|
|
188
|
+
profile: session.profile,
|
|
189
|
+
account: session.account,
|
|
190
|
+
already_linked: session.alreadyLinked,
|
|
191
|
+
...(session.received ? { received: session.received } : {}),
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
annotate(logsInOrOut(session.command("end")), { effects: REMOTE_WRITE, examples: ["wa personal session end"] })
|
|
195
|
+
.description("unlink this device on WhatsApp's side and delete its keys here")
|
|
196
|
+
.action(async function () {
|
|
197
|
+
await end(this);
|
|
198
|
+
});
|
|
199
|
+
return session;
|
|
200
|
+
};
|
|
201
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAA;AAe3C,eAAO,MAAM,YAAY,eA2JnB,CAAA"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { accessSync, constants, existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { CliError, indent, renderPretty, singleLine } from "@wirecat/cli-base";
|
|
3
|
+
import { annotate } from "@wirecat/cli-base/commands";
|
|
4
|
+
import { installSkill } from "@wirecat/cli-base/skill";
|
|
5
|
+
import { AGENTS, agentFor, asFirstWord, commandWords, environmentOf, logsInOrOut, messengerContext, printItem, REMOTE_WRITE, refuseCommandName, rootOf, runtime, screenFor, secretInputOf, } from "@wirecat/cli-core/cli";
|
|
6
|
+
import { levelFor } from "@wirecat/cli-core/sends";
|
|
7
|
+
import { Command, Option } from "commander";
|
|
8
|
+
import { WA } from "../app.js";
|
|
9
|
+
import { SKILL, WHATSAPP } from "../messenger.js";
|
|
10
|
+
import { pathsFor, privateStore } from "../paths.js";
|
|
11
|
+
import { installer, PACKAGE } from "../update.js";
|
|
12
|
+
import { startSession } from "./session.js";
|
|
13
|
+
const STEPS = 5;
|
|
14
|
+
const chatCount = (count) => `${count} ${count === 1 ? "chat" : "chats"}`;
|
|
15
|
+
export const setupCommand = () => annotate(logsInOrOut(new Command("setup")), {
|
|
16
|
+
effects: REMOTE_WRITE,
|
|
17
|
+
lifetime: "interactive",
|
|
18
|
+
mcp: false,
|
|
19
|
+
examples: ["wa personal setup", "wa personal setup --agent codex", "wa personal setup --agent claude --json"],
|
|
20
|
+
})
|
|
21
|
+
.description("set up WhatsApp and connect your agent")
|
|
22
|
+
.configureHelp({ showGlobalOptions: true })
|
|
23
|
+
.addHelpText("after", "\nExamples:\n" +
|
|
24
|
+
" wa personal setup Guided setup of profile personal in your local terminal\n" +
|
|
25
|
+
" wa personal setup --agent codex Install the skill for Codex\n" +
|
|
26
|
+
" wa work setup --agent claude Set up a separate work profile\n" +
|
|
27
|
+
" wa personal setup --method phone Link with a pairing code instead of QR\n" +
|
|
28
|
+
"\nThe first word names the profile; every later command names it too.\n" +
|
|
29
|
+
"\nAllow about 5 minutes: the phone pushes your recent history once, right after linking.\n" +
|
|
30
|
+
"Scan the QR in WhatsApp: Settings > Linked devices > Link a device.\n" +
|
|
31
|
+
"Type your phone number only in the terminal.\n" +
|
|
32
|
+
"\nAgents: read `wa skill show` first. Without a terminal, setup prints the QR code as text:\n" +
|
|
33
|
+
" wa personal setup --agent codex --json\n" +
|
|
34
|
+
"Run it in the background and paste each QR block into the chat, as for `session start qr`.\n" +
|
|
35
|
+
"Machine mode skips agent installation unless --agent is given.\n" +
|
|
36
|
+
"A device linked before is checked without linking again.\n" +
|
|
37
|
+
"\nSetup reads five chats from the local store. To keep receiving messages:\n" +
|
|
38
|
+
" wa personal server install\n")
|
|
39
|
+
.addOption(new Option("--agent <agent>", "install the skill for this agent; asks at a terminal, otherwise none").choices(AGENTS))
|
|
40
|
+
.addOption(new Option("--method <method>", "how to log in when there is no session").choices(["qr", "phone"]).default("qr"))
|
|
41
|
+
.action(async function () {
|
|
42
|
+
const context = messengerContext(this, WHATSAPP);
|
|
43
|
+
refuseCommandName(context.profile, commandWords(rootOf(this)), "wa");
|
|
44
|
+
const options = this.opts();
|
|
45
|
+
if (context.settings.offline)
|
|
46
|
+
throw new CliError("validation_error", "wa setup verifies WhatsApp — remove --offline");
|
|
47
|
+
for (const permission of ["account.show", "chats.list"]) {
|
|
48
|
+
if (levelFor(context.settings.permissions, permission).level === "deny")
|
|
49
|
+
throw new CliError("permission_error", `profile ${context.profile} denies ${permission} — setup cannot verify it`, { permission });
|
|
50
|
+
}
|
|
51
|
+
const devicePath = privateStore(context.profile, context.env);
|
|
52
|
+
if (!existsSync(devicePath) && !context.stdin.isTTY && options.method === "phone")
|
|
53
|
+
throw new CliError("validation_error", "wa setup --method phone needs a terminal to ask for the number — run it locally, or link by QR", { reason: "input.required" });
|
|
54
|
+
const environment = environmentOf(this);
|
|
55
|
+
const { platform } = environment;
|
|
56
|
+
const prefix = `wa ${asFirstWord(context.profile)}`;
|
|
57
|
+
const command = installer(environmentOf(this).update) === "npx"
|
|
58
|
+
? `npm${platform === "win32" ? ".cmd" : ""} exec --yes --package=${PACKAGE} -- ${prefix}`
|
|
59
|
+
: prefix;
|
|
60
|
+
// The command's own signal, not a phase's: Ctrl+C during the history wait ends the wait, not setup.
|
|
61
|
+
const signal = environment.commandSignal ?? new AbortController().signal;
|
|
62
|
+
const screen = screenFor(context, this.optsWithGlobals().quiet === true, STEPS);
|
|
63
|
+
const linkContext = { ...context, renderer: { ...context.renderer, note: screen.detail } };
|
|
64
|
+
screen.title(`WhatsApp setup — profile ${context.profile}. Allow about 5 minutes; the phone sends recent history once.`);
|
|
65
|
+
screen.step(1, "This computer");
|
|
66
|
+
const paths = pathsFor(context.env);
|
|
67
|
+
for (const path of [paths.config, paths.state, paths.cache]) {
|
|
68
|
+
mkdirSync(path, { recursive: true });
|
|
69
|
+
accessSync(path, constants.W_OK);
|
|
70
|
+
}
|
|
71
|
+
screen.detail("✓ local directories ready");
|
|
72
|
+
if (platform === "win32")
|
|
73
|
+
screen.detail("Windows: use wa.cmd or npm.cmd if PowerShell blocks scripts. Open a new terminal after installing Node.js.");
|
|
74
|
+
screen.step(2, "Link this device");
|
|
75
|
+
const session = await startSession(this, linkContext, {
|
|
76
|
+
signal,
|
|
77
|
+
method: options.method,
|
|
78
|
+
command: `${prefix}setup`,
|
|
79
|
+
indent: screen.indent,
|
|
80
|
+
stopEndsWait: true,
|
|
81
|
+
});
|
|
82
|
+
environment.endUntilStopped?.();
|
|
83
|
+
const reused = session.alreadyLinked;
|
|
84
|
+
const history = session.received;
|
|
85
|
+
screen.detail(history
|
|
86
|
+
? `✓ linked; ${chatCount(history.chats)} and ${history.messages} messages kept from the phone`
|
|
87
|
+
: "✓ existing device, no new link");
|
|
88
|
+
screen.step(3, "Account");
|
|
89
|
+
const account = await context.withMessenger(async (adapter) => {
|
|
90
|
+
signal.throwIfAborted();
|
|
91
|
+
return adapter.me();
|
|
92
|
+
});
|
|
93
|
+
screen.detail(`✓ ${account.name === null ? "verified" : singleLine(account.name)}`);
|
|
94
|
+
screen.step(4, "A few chats");
|
|
95
|
+
// WhatsApp has no chat list to ask for: the store holds what the phone pushed and what serve received.
|
|
96
|
+
const chats = await context.withStore((store, key) => store.forAccount(key).chats.chats({ limit: 5, offset: 0 }));
|
|
97
|
+
screen.detail(`✓ ${chatCount(chats.items.length)} read from the local store`);
|
|
98
|
+
if (chats.items.length === 0)
|
|
99
|
+
screen.detail(`nothing kept yet — \`${command}server install\` starts receiving`);
|
|
100
|
+
screen.step(5, "Agent");
|
|
101
|
+
const agent = await agentFor(context, options.agent, screen.indent, { ...secretInputOf(this), signal });
|
|
102
|
+
screen.detail(agent === "none" ? "✓ no agent skill installed" : `✓ ${agent}`);
|
|
103
|
+
const targets = agent === "all" ? ["claude", "agents"] : [agent === "claude" ? "claude" : "agents"];
|
|
104
|
+
signal.throwIfAborted();
|
|
105
|
+
const written = agent === "none" ? [] : installSkill(WA, SKILL, { targets, env: context.env });
|
|
106
|
+
const next = {
|
|
107
|
+
instructions: `${command}skill show`,
|
|
108
|
+
inbox: `${command}inbox --limit 5`,
|
|
109
|
+
chats: `${command}chats list --limit 5`,
|
|
110
|
+
receive: `${command}server install`,
|
|
111
|
+
history_status: `${command}store status`,
|
|
112
|
+
...(agent === "none" ? { skill: `${command}skill install`, mcp: `${command}mcp config` } : {}),
|
|
113
|
+
};
|
|
114
|
+
const answer = {
|
|
115
|
+
profile: context.profile,
|
|
116
|
+
runtime: runtime(),
|
|
117
|
+
paths,
|
|
118
|
+
device: { path: devicePath, reused },
|
|
119
|
+
account: { id: account.id, name: account.name },
|
|
120
|
+
...(history ? { history } : {}),
|
|
121
|
+
chats: { checked: chats.items.length, has_more: chats.hasMore },
|
|
122
|
+
agent: { name: agent, written },
|
|
123
|
+
next,
|
|
124
|
+
};
|
|
125
|
+
if (context.format !== "pretty")
|
|
126
|
+
printItem(context, answer);
|
|
127
|
+
else {
|
|
128
|
+
const rows = {
|
|
129
|
+
"Try now": next.inbox,
|
|
130
|
+
"Keep receiving": `${next.receive} (a background server saves new messages)`,
|
|
131
|
+
"Agent skill": agent === "none"
|
|
132
|
+
? `skipped — install later: ${next.skill}`
|
|
133
|
+
: `installed for ${agent}; start a new agent session if it is not found`,
|
|
134
|
+
"For an agent": next.instructions,
|
|
135
|
+
};
|
|
136
|
+
context.streams.data(`\n✓ WhatsApp is ready — profile ${context.profile}, ${chatCount(chats.items.length)} checked\n\n` +
|
|
137
|
+
indent(renderPretty(rows, { color: context.color }), 2));
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,mCAexB,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { annotate } from "@wirecat/cli-base/commands";
|
|
2
|
+
import { environmentOf, outputFor, restartServers, upgradeCommand as sharedUpgradeCommand } from "@wirecat/cli-core/cli";
|
|
3
|
+
import { WA } from "../app.js";
|
|
4
|
+
import { installer, latest, PACKAGE, runUpdate, waScript } from "../update.js";
|
|
5
|
+
export const upgradeCommand = () => annotate(sharedUpgradeCommand(WA, PACKAGE, (command) => {
|
|
6
|
+
const context = environmentOf(command);
|
|
7
|
+
const environment = context.update ?? {};
|
|
8
|
+
const env = context.env ?? process.env;
|
|
9
|
+
return {
|
|
10
|
+
...outputFor(command),
|
|
11
|
+
installer: () => installer(environment),
|
|
12
|
+
latest: () => latest(environment),
|
|
13
|
+
install: (argv) => runUpdate(argv, environment),
|
|
14
|
+
afterUpdate: () => restartServers(WA, waScript(), env, environment.spawn),
|
|
15
|
+
};
|
|
16
|
+
}), { examples: ["wa upgrade --check", "wa upgrade"] });
|
|
17
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,IAAI,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACxH,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAA;AAE9B,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE9E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE,CACjC,QAAQ,CACN,oBAAoB,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE;IAC5C,MAAM,OAAO,GAAG,aAAa,CAAc,OAAO,CAAC,CAAA;IACnD,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAA;IACxC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAA;IACtC,OAAO;QACL,GAAG,SAAS,CAAC,OAAO,CAAC;QACrB,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC;QACvC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;QACjC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC;QAC/C,WAAW,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC;KAC1E,CAAA;AACH,CAAC,CAAC,EACF,EAAE,QAAQ,EAAE,CAAC,oBAAoB,EAAE,YAAY,CAAC,EAAE,CACnD,CAAA"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type UpdateEnvironment } from "./update.js";
|
|
2
|
+
/** Whether the engine binary is there to start — never started here. */
|
|
3
|
+
export declare const engineState: (env: NodeJS.ProcessEnv, update?: UpdateEnvironment) => {
|
|
4
|
+
path: string;
|
|
5
|
+
found: boolean;
|
|
6
|
+
hint?: undefined;
|
|
7
|
+
} | {
|
|
8
|
+
path: string;
|
|
9
|
+
found: boolean;
|
|
10
|
+
hint: string;
|
|
11
|
+
};
|
|
12
|
+
/** The device keys' file modes, from `stat` alone: the keys are a credential and are never opened here. */
|
|
13
|
+
export declare const deviceModes: (storePath: string, platform?: NodeJS.Platform) => {
|
|
14
|
+
checked: boolean;
|
|
15
|
+
reason: string;
|
|
16
|
+
ok?: undefined;
|
|
17
|
+
problems?: undefined;
|
|
18
|
+
} | {
|
|
19
|
+
reason?: undefined;
|
|
20
|
+
checked: boolean;
|
|
21
|
+
ok: boolean;
|
|
22
|
+
problems: {
|
|
23
|
+
path: string;
|
|
24
|
+
mode: string;
|
|
25
|
+
want: string;
|
|
26
|
+
fix: string;
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Who last held the device's lock, from the name the engine writes into it. The engine never clears that name, so
|
|
31
|
+
* the holder counts as running only while a process with its pid is.
|
|
32
|
+
*/
|
|
33
|
+
export declare const lockState: (lockPath: string) => {
|
|
34
|
+
path: string;
|
|
35
|
+
holder: string | null;
|
|
36
|
+
pid: number | null;
|
|
37
|
+
running: boolean;
|
|
38
|
+
};
|
|
39
|
+
/** `doctor`'s WhatsApp block: the engine, the device keys and the lock, read from disk without starting anything. */
|
|
40
|
+
export declare const diagnoseWhatsApp: (profile: string, env: NodeJS.ProcessEnv, update?: UpdateEnvironment) => {
|
|
41
|
+
engine: {
|
|
42
|
+
path: string;
|
|
43
|
+
found: boolean;
|
|
44
|
+
hint?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
path: string;
|
|
47
|
+
found: boolean;
|
|
48
|
+
hint: string;
|
|
49
|
+
};
|
|
50
|
+
device: {
|
|
51
|
+
path: string;
|
|
52
|
+
exists: boolean;
|
|
53
|
+
files: {
|
|
54
|
+
checked: boolean;
|
|
55
|
+
reason: string;
|
|
56
|
+
ok?: undefined;
|
|
57
|
+
problems?: undefined;
|
|
58
|
+
} | {
|
|
59
|
+
reason?: undefined;
|
|
60
|
+
checked: boolean;
|
|
61
|
+
ok: boolean;
|
|
62
|
+
problems: {
|
|
63
|
+
path: string;
|
|
64
|
+
mode: string;
|
|
65
|
+
want: string;
|
|
66
|
+
fix: string;
|
|
67
|
+
}[];
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
lock: {
|
|
71
|
+
path: string;
|
|
72
|
+
holder: string | null;
|
|
73
|
+
pid: number | null;
|
|
74
|
+
running: boolean;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=diagnose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../src/diagnose.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAI/D,wEAAwE;AACxE,eAAO,MAAM,WAAW,QAAS,MAAM,CAAC,UAAU,WAAU,iBAAiB;;;;;;;;CAY5E,CAAA;AAED,2GAA2G;AAC3G,eAAO,MAAM,WAAW,cAAe,MAAM,aAAY,MAAM,CAAC,QAAQ;;;;;;;;;;;;;;;CAoBvE,CAAA;AAWD;;;GAGG;AACH,eAAO,MAAM,SAAS,aAAc,MAAM;;;;;CAazC,CAAA;AAED,qHAAqH;AACrH,eAAO,MAAM,gBAAgB,YAAa,MAAM,OAAO,MAAM,CAAC,UAAU,WAAW,iBAAiB;IAGhG,MAAM;;;;;;;;;IACN,MAAM;QAAI,IAAI;QAAS,MAAM;QAAqB,KAAK;;;;;;;;;;;;;;;;;IACvD,IAAI;;;;;;CAEP,CAAA"}
|