@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
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { resolve as absolute, extname, join } from "node:path";
|
|
6
|
+
import { CliError } from "@wirecat/cli-base";
|
|
7
|
+
import { bareCheck, parseMarkdownSpans, } from "@wirecat/cli-core";
|
|
8
|
+
import { EngineError, OLDER_MAX, } from "../engine/contract.js";
|
|
9
|
+
import { channelAdapter, channelHistory, channelWrites, isChannel, refuseChannelPost } from "./channels.js";
|
|
10
|
+
import { fromEngine } from "./errors.js";
|
|
11
|
+
import { toWhatsApp } from "./format-markdown.js";
|
|
12
|
+
import { groupAdapter } from "./groups.js";
|
|
13
|
+
import { isFile, sameFile, toAccount, toChat, toChatEvent, toChatUpdate, toMember, toMessage, toWaAttachment, } from "./map.js";
|
|
14
|
+
import { pinAdapter } from "./pins.js";
|
|
15
|
+
import { pollAdapter, toHistoryVote, toVoteEvent } from "./polls.js";
|
|
16
|
+
import { privacyAdapter } from "./privacy.js";
|
|
17
|
+
import { AFTER_EVERY_MESSAGE, settingsAdapter, settingsWrite } from "./settings.js";
|
|
18
|
+
// WhatsApp addresses a message by its sender and by whether it is the account's own, and the engine keeps no
|
|
19
|
+
// messages, so an edit, a deletion, a reaction or a read receipt looks the message up in cli-core's store first.
|
|
20
|
+
const NOTHING_STORED = {
|
|
21
|
+
message: async () => undefined,
|
|
22
|
+
newestIncoming: async () => undefined,
|
|
23
|
+
anchor: async () => undefined,
|
|
24
|
+
wroteTo: async () => false,
|
|
25
|
+
pollVotes: async () => [],
|
|
26
|
+
};
|
|
27
|
+
// whatsmeow's EditWindow: WhatsApp clients ignore an edit that comes later.
|
|
28
|
+
const EDIT_WINDOW_MS = 20 * 60 * 1000;
|
|
29
|
+
/** Options WhatsApp has no way to honour; `noPreview` is always true, since nothing here builds link previews. */
|
|
30
|
+
const REFUSED = ["threadId", "markup", "sticker", "spoiler", "captionAbove"];
|
|
31
|
+
const translated = async (work) => {
|
|
32
|
+
try {
|
|
33
|
+
return await work;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error instanceof EngineError)
|
|
37
|
+
throw fromEngine(error);
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const hit = (message) => ({ ...message, chatTitle: null });
|
|
42
|
+
const PHONE_CHAT = /^\d+@s\.whatsapp\.net$/;
|
|
43
|
+
const ENDED = {
|
|
44
|
+
logged_out: (words) => fromEngine(new EngineError("authentication_error", `WhatsApp logged this device out — log in again with ${words("session.start")}`, "device.logged-out")),
|
|
45
|
+
replaced: () => fromEngine(new EngineError("provider_unavailable", "another process took over this WhatsApp login; only one may hold it", "device.replaced")),
|
|
46
|
+
banned: (_words, until) => fromEngine(new EngineError("permission_error", "WhatsApp has banned or restricted this account; see the phone", "account.banned", until)),
|
|
47
|
+
outdated: () => fromEngine(new EngineError("provider_unavailable", "WhatsApp no longer accepts this version of wa; update it", "client.outdated")),
|
|
48
|
+
stopped: () => fromEngine(new EngineError("provider_unavailable", "the WhatsApp engine stopped unexpectedly", "engine.stopped")),
|
|
49
|
+
};
|
|
50
|
+
const ENDING = new Set([
|
|
51
|
+
...Object.values(ENDED).map((end) => end(bareCheck).details.reason),
|
|
52
|
+
"engine.stopped-mid-write",
|
|
53
|
+
]);
|
|
54
|
+
/** A failure that means the connection is gone, not that one event was odd: it ends the listening. */
|
|
55
|
+
const ends = (error) => (error instanceof EngineError && ENDING.has(error.reason)) ||
|
|
56
|
+
(error instanceof CliError && ENDING.has(error.details.reason));
|
|
57
|
+
/**
|
|
58
|
+
* Hands each event on until `signal` aborts; a connection WhatsApp ended rejects with why, unless `expected` says this
|
|
59
|
+
* process asked for that end. Events are handled one at a time in arrival order. One whose handling fails is skipped
|
|
60
|
+
* and the next still runs: a stalled queue would keep every later push out of the store until a restart. The first skip
|
|
61
|
+
* is said on `warn` at once, kind and code only, never its content; `drained` settles when the handling caught up and
|
|
62
|
+
* then says how many were skipped if there were more.
|
|
63
|
+
*/
|
|
64
|
+
const listening = (engine, kinds, signal, words, warn, handle, expected = () => false) => {
|
|
65
|
+
let stop = () => { };
|
|
66
|
+
let queue = Promise.resolve();
|
|
67
|
+
let skipped = 0;
|
|
68
|
+
let fail = () => { };
|
|
69
|
+
const run = (kind, work) => {
|
|
70
|
+
queue = queue.then(work).catch((error) => fail(kind, error));
|
|
71
|
+
};
|
|
72
|
+
const done = new Promise((resolve, reject) => {
|
|
73
|
+
fail = (kind, error) => {
|
|
74
|
+
if (ends(error))
|
|
75
|
+
return reject(error instanceof EngineError ? fromEngine(error) : error);
|
|
76
|
+
skipped += 1;
|
|
77
|
+
if (skipped > 1)
|
|
78
|
+
return;
|
|
79
|
+
const code = error instanceof CliError ? error.code : error instanceof Error ? error.name : "error";
|
|
80
|
+
warn(`a pushed ${kind} event could not be handled and was skipped (${code}); the ones after it go on, ` +
|
|
81
|
+
"and any more skips are counted when wa stops listening");
|
|
82
|
+
};
|
|
83
|
+
const unlisten = engine.listen(kinds, (event) => {
|
|
84
|
+
if (event.event === "connection" && expected(event.state))
|
|
85
|
+
return resolve();
|
|
86
|
+
const ended = event.event === "connection" ? ENDED[event.state]?.(words, event.until) : undefined;
|
|
87
|
+
if (ended)
|
|
88
|
+
reject(ended);
|
|
89
|
+
else
|
|
90
|
+
run(event.event, () => handle(event));
|
|
91
|
+
});
|
|
92
|
+
const aborted = () => resolve();
|
|
93
|
+
signal.addEventListener("abort", aborted, { once: true });
|
|
94
|
+
stop = () => {
|
|
95
|
+
unlisten();
|
|
96
|
+
signal.removeEventListener("abort", aborted);
|
|
97
|
+
};
|
|
98
|
+
if (signal.aborted)
|
|
99
|
+
resolve();
|
|
100
|
+
});
|
|
101
|
+
// The caller may still be awaiting the engine's readiness when an ended connection rejects `done`.
|
|
102
|
+
done.catch(() => { });
|
|
103
|
+
const drained = () => queue.then(() => {
|
|
104
|
+
if (skipped > 1)
|
|
105
|
+
warn(`${skipped} pushed events could not be handled and were skipped in all`);
|
|
106
|
+
});
|
|
107
|
+
return { done, stop, drained, run };
|
|
108
|
+
};
|
|
109
|
+
/** Re-keys that arrive this close together go to cli-core as one batch, up to this many. */
|
|
110
|
+
const REKEY_WINDOW_MS = 100;
|
|
111
|
+
const REKEY_BATCH = 500;
|
|
112
|
+
const VIDEO = new Set([".mp4", ".m4v", ".mov"]);
|
|
113
|
+
/** As tg sends them: a photo as a photo, a voice as a voice, a video as a video unless `--as-file`, the rest as files. */
|
|
114
|
+
const uploadKind = ({ kind, name, asFile }) => kind === "photo" || kind === "voice" ? kind : !asFile && VIDEO.has(extname(name).toLowerCase()) ? "video" : "document";
|
|
115
|
+
/** A folder only this user can read, gone when `work` ends: the engine writes a download into it, or reads bytes made in memory. */
|
|
116
|
+
const inPrivateFolder = async (work) => {
|
|
117
|
+
const folder = await mkdtemp(join(tmpdir(), "wa-media-"));
|
|
118
|
+
try {
|
|
119
|
+
return await work(folder);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
await rm(folder, { recursive: true, force: true });
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const onDisk = async (source, work) => {
|
|
126
|
+
if (source.kind === "file")
|
|
127
|
+
return work(absolute(source.path));
|
|
128
|
+
return inPrivateFolder(async (folder) => {
|
|
129
|
+
const path = join(folder, "upload");
|
|
130
|
+
await writeFile(path, source.bytes, { mode: 0o600, flag: "wx" });
|
|
131
|
+
return work(path);
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
const allOnDisk = async (files, work, placed = []) => {
|
|
135
|
+
const [next, ...rest] = files;
|
|
136
|
+
if (!next)
|
|
137
|
+
return work(placed);
|
|
138
|
+
return onDisk(next.upload.source, (path) => allOnDisk(rest, work, [...placed, { ...next, path }]));
|
|
139
|
+
};
|
|
140
|
+
const quoted = (message) => ({
|
|
141
|
+
id: message.id,
|
|
142
|
+
senderId: message.senderId,
|
|
143
|
+
senderName: message.senderName,
|
|
144
|
+
timestamp: message.timestamp,
|
|
145
|
+
text: message.text,
|
|
146
|
+
attachments: message.attachments,
|
|
147
|
+
outgoing: message.outgoing ?? null,
|
|
148
|
+
});
|
|
149
|
+
const keyOf = (chatId, message) => ({
|
|
150
|
+
chat: chatId,
|
|
151
|
+
id: message.id,
|
|
152
|
+
fromMe: message.outgoing === true,
|
|
153
|
+
sender: message.senderId,
|
|
154
|
+
});
|
|
155
|
+
export const whatsAppAdapter = (engine, stored = NOTHING_STORED, words = bareCheck,
|
|
156
|
+
/** Where a skipped pushed event is said — a warning, so `--quiet` drops it. The diagnostic stream if not given. */
|
|
157
|
+
warn = (line) => process.stderr.write(`${line}\n`)) => {
|
|
158
|
+
// A guessed key would make WhatsApp drop the change without a word, so a message the store lacks is refused.
|
|
159
|
+
const held = async (chatId, messageId) => {
|
|
160
|
+
const message = await stored.message(chatId, messageId);
|
|
161
|
+
if (!message)
|
|
162
|
+
throw new CliError("not_found", `that message is not in the local store, and WhatsApp needs its sender to address it; ${words("serve")} keeps the store filled`);
|
|
163
|
+
return message;
|
|
164
|
+
};
|
|
165
|
+
// Set by `session end`: WhatsApp then ends the connection as logged out, which is the answer, not a failure.
|
|
166
|
+
let loggingOut = false;
|
|
167
|
+
// Held re-keys of a running `feed`: a live event may name the new id, and must not reach cli-core before them (§5).
|
|
168
|
+
const holding = new Set();
|
|
169
|
+
const handingOn = (onEvent, signal, expected) => {
|
|
170
|
+
const handed = async (event) => {
|
|
171
|
+
for (const handOn of holding)
|
|
172
|
+
handOn();
|
|
173
|
+
if (event.event === "message")
|
|
174
|
+
onEvent({ event: "message", message: hit(toMessage(event.message)) });
|
|
175
|
+
else if (event.event === "edit")
|
|
176
|
+
onEvent({ event: "edit", message: hit(toMessage(event.message)) });
|
|
177
|
+
else if (event.event === "delete")
|
|
178
|
+
onEvent({
|
|
179
|
+
event: "delete",
|
|
180
|
+
chatId: event.chat,
|
|
181
|
+
chatTitle: null,
|
|
182
|
+
messageId: event.id,
|
|
183
|
+
});
|
|
184
|
+
else if (event.event === "star")
|
|
185
|
+
onEvent({
|
|
186
|
+
event: "star",
|
|
187
|
+
chatId: event.chat,
|
|
188
|
+
chatTitle: null,
|
|
189
|
+
messageId: event.id,
|
|
190
|
+
starred: event.starred,
|
|
191
|
+
});
|
|
192
|
+
else if (event.event === "vote") {
|
|
193
|
+
const vote = await toVoteEvent(event.vote, stored);
|
|
194
|
+
if (vote)
|
|
195
|
+
onEvent(vote);
|
|
196
|
+
}
|
|
197
|
+
else if (event.event === "chat_event")
|
|
198
|
+
onEvent({
|
|
199
|
+
event: "chat_event",
|
|
200
|
+
chatId: event.change.chat,
|
|
201
|
+
chatTitle: null,
|
|
202
|
+
change: toChatEvent(event.change),
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
// In arrival order: a vote reads its poll from the store, and nothing after it may overtake it.
|
|
206
|
+
const live = listening(engine, ["message", "edit", "delete", "vote", "star", "chat_event", "connection"], signal, words, warn, handed, expected);
|
|
207
|
+
return {
|
|
208
|
+
done: live.done,
|
|
209
|
+
stop: async () => {
|
|
210
|
+
live.stop();
|
|
211
|
+
await live.drained();
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
// A push after a re-link carries the path the file had then, and the store may hold the one the phone uploaded
|
|
216
|
+
// again. cli-core keeps a stored ref only when the pushed file has none, so the pushed one is left off when it names
|
|
217
|
+
// the same file; another file keeps its own. Only a message with a ref costs a store read; one that fails hands the
|
|
218
|
+
// message on as pushed, never loses it.
|
|
219
|
+
const withoutKeptRefs = async (message) => {
|
|
220
|
+
if (!message.attachments.some((file) => file.providerRef))
|
|
221
|
+
return message;
|
|
222
|
+
const kept = await stored.message(message.chatId, message.id).catch(() => undefined);
|
|
223
|
+
if (!kept?.attachments.some((file) => file.providerRef))
|
|
224
|
+
return message;
|
|
225
|
+
return {
|
|
226
|
+
...message,
|
|
227
|
+
attachments: message.attachments.map((file, position) => {
|
|
228
|
+
if (!sameFile(file.providerRef, kept.attachments[position]?.providerRef))
|
|
229
|
+
return file;
|
|
230
|
+
const { providerRef: _pushed, ...rest } = file;
|
|
231
|
+
return rest;
|
|
232
|
+
}),
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
const pushing = async (onBatch, signal, expected) => {
|
|
236
|
+
// cli-core saves each batch's re-keys apart, so thousands at a serve's start must not come one batch each; a push
|
|
237
|
+
// hands on the held ones before its own, as they arrived.
|
|
238
|
+
let held = [];
|
|
239
|
+
let due;
|
|
240
|
+
const flush = () => {
|
|
241
|
+
clearTimeout(due);
|
|
242
|
+
due = undefined;
|
|
243
|
+
if (held.length === 0)
|
|
244
|
+
return;
|
|
245
|
+
const rekeys = held;
|
|
246
|
+
held = [];
|
|
247
|
+
onBatch({ rekeys });
|
|
248
|
+
};
|
|
249
|
+
// In arrival order: a push waits for its store reads, and a re-key after it must not overtake it.
|
|
250
|
+
const handed = async (event) => {
|
|
251
|
+
if (event.event === "rekey") {
|
|
252
|
+
held.push({ from: event.from, to: event.to });
|
|
253
|
+
if (held.length >= REKEY_BATCH)
|
|
254
|
+
flush();
|
|
255
|
+
else
|
|
256
|
+
due ??= setTimeout(() => pushes.run("rekey", flush), REKEY_WINDOW_MS);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (event.event !== "history")
|
|
260
|
+
return;
|
|
261
|
+
flush();
|
|
262
|
+
const { rekeys, chats, contacts, messages, votes, events } = event.history;
|
|
263
|
+
onBatch({
|
|
264
|
+
rekeys: rekeys ?? [],
|
|
265
|
+
chats: chats.map(toChatUpdate),
|
|
266
|
+
people: contacts.map(toMember),
|
|
267
|
+
messages: await Promise.all(messages.map((message) => withoutKeptRefs(toMessage(message)))),
|
|
268
|
+
votes: votes.flatMap((vote) => toHistoryVote(vote) ?? []),
|
|
269
|
+
events: (events ?? []).map((change) => ({ chatId: change.chat, change: toChatEvent(change) })),
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
const pushes = listening(engine, ["history", "rekey", "connection"], signal, words, warn, handed, expected);
|
|
273
|
+
const handOn = () => {
|
|
274
|
+
try {
|
|
275
|
+
flush();
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
pushes.run("rekey", () => Promise.reject(error));
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
holding.add(handOn);
|
|
282
|
+
try {
|
|
283
|
+
await pushes.done;
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
holding.delete(handOn);
|
|
287
|
+
pushes.stop();
|
|
288
|
+
pushes.run("rekey", flush);
|
|
289
|
+
await pushes.drained();
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
const ownLogout = (state) => state === "logged_out" && loggingOut;
|
|
293
|
+
// A deletion for the account alone, a star and a chat marked read are changes to its synced settings, not messages.
|
|
294
|
+
const synced = settingsWrite(translated, words);
|
|
295
|
+
// The phone's new upload replaces the whole stored ref on `file`, so cli-core saves it and a later download or a
|
|
296
|
+
// forward uses the live path; a second read of the same file in this run uses it too.
|
|
297
|
+
async function* fetched(file, attachment, key) {
|
|
298
|
+
const folder = await mkdtemp(join(tmpdir(), "wa-media-"));
|
|
299
|
+
try {
|
|
300
|
+
const path = join(folder, "file");
|
|
301
|
+
const renewed = await translated(engine.download(attachment, path, key));
|
|
302
|
+
if (renewed) {
|
|
303
|
+
// The old URL names the dead copy; without one, the engine builds it from the new path.
|
|
304
|
+
const { url: _dead, ...kept } = attachment.ref;
|
|
305
|
+
attachment.ref = { ...kept, ...renewed };
|
|
306
|
+
file.providerRef = attachment.ref;
|
|
307
|
+
}
|
|
308
|
+
yield* createReadStream(path);
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
await rm(folder, { recursive: true, force: true });
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const core = {
|
|
315
|
+
formatMarkdown: async (text) => parseMarkdownSpans(text),
|
|
316
|
+
self: () => engine.self(),
|
|
317
|
+
newSendId: () => `3EB0${randomBytes(9).toString("hex").toUpperCase()}`,
|
|
318
|
+
me: async () => toAccount(await translated(engine.me())),
|
|
319
|
+
// A send to a phone-form chat lands under the LID the engine answers, so every later command must address that
|
|
320
|
+
// chat too, or a delete, a star or a vote by the typed number misses the stored message (§5).
|
|
321
|
+
resolve: async (query) => {
|
|
322
|
+
if (query.includes("@"))
|
|
323
|
+
return {
|
|
324
|
+
id: PHONE_CHAT.test(query) ? await translated(engine.canonicalChat(query)) : query,
|
|
325
|
+
title: null,
|
|
326
|
+
kind: "unknown",
|
|
327
|
+
unreadCount: null,
|
|
328
|
+
lastMessageAt: null,
|
|
329
|
+
participantsCount: null,
|
|
330
|
+
};
|
|
331
|
+
const named = (await translated(engine.directory())).filter((chat) => chat.name === query);
|
|
332
|
+
if (named.length === 1 && named[0])
|
|
333
|
+
return toChat(named[0]);
|
|
334
|
+
if (named.length > 1)
|
|
335
|
+
throw new CliError("validation_error", `${named.length} chats share that name — name one by its id; ${words("chats.list")} shows them`);
|
|
336
|
+
throw new CliError("not_found", `no chat by that name or id; ${words("chats.list")} shows the chats this profile has`);
|
|
337
|
+
},
|
|
338
|
+
chat: async (jid) => {
|
|
339
|
+
const card = await translated(engine.chat(jid));
|
|
340
|
+
return { ...toChat(card.chat), members: card.members?.map(toMember) ?? null };
|
|
341
|
+
},
|
|
342
|
+
send: async (chatId, text, options) => {
|
|
343
|
+
const refused = REFUSED.filter((option) => options[option] !== undefined && options[option] !== false);
|
|
344
|
+
if (refused.length > 0)
|
|
345
|
+
throw new CliError("validation_error", `WhatsApp cannot send with ${refused.join(", ")}`);
|
|
346
|
+
const uploads = options.attachments ?? [];
|
|
347
|
+
const [upload] = uploads;
|
|
348
|
+
const files = uploads.map((one) => ({ upload: one, kind: uploadKind(one) }));
|
|
349
|
+
if (files.length > 1 && files.some(({ kind }) => kind !== "photo" && kind !== "video"))
|
|
350
|
+
throw new CliError("validation_error", "a WhatsApp album holds photos and videos only; send a document in a message of its own");
|
|
351
|
+
if (upload?.kind === "voice" && text.trim() !== "")
|
|
352
|
+
throw new CliError("validation_error", "WhatsApp sends a voice message alone, without text");
|
|
353
|
+
const { stickerFile } = options;
|
|
354
|
+
// Untried on a live channel, where a post carries a URL and no key.
|
|
355
|
+
if (stickerFile && isChannel(chatId))
|
|
356
|
+
throw new CliError("validation_error", "wa does not post stickers to a WhatsApp channel yet");
|
|
357
|
+
if (isChannel(chatId))
|
|
358
|
+
await refuseChannelPost(engine, translated, chatId, {
|
|
359
|
+
files: files.length,
|
|
360
|
+
reply: options.replyTo !== undefined,
|
|
361
|
+
});
|
|
362
|
+
// A reply to a message the store lacks still goes, with its id alone.
|
|
363
|
+
const answered = options.replyTo === undefined ? undefined : await stored.message(chatId, options.replyTo);
|
|
364
|
+
const request = {
|
|
365
|
+
chat: chatId,
|
|
366
|
+
text: options.formatting ? toWhatsApp(text, options.formatting) : text,
|
|
367
|
+
id: options.sendId,
|
|
368
|
+
...(options.replyTo === undefined ? {} : { replyTo: options.replyTo }),
|
|
369
|
+
...(answered
|
|
370
|
+
? { quoted: { fromMe: answered.outgoing === true, sender: answered.senderId, text: answered.text } }
|
|
371
|
+
: {}),
|
|
372
|
+
};
|
|
373
|
+
const message = await translated(files.length > 1
|
|
374
|
+
? allOnDisk(files, (placed) => engine.sendAlbum({
|
|
375
|
+
...request,
|
|
376
|
+
files: placed.map(({ upload, kind, path }) => ({ kind, path, name: upload.name })),
|
|
377
|
+
}))
|
|
378
|
+
: upload
|
|
379
|
+
? onDisk(upload.source, (path) => engine.sendMedia({ ...request, file: { kind: uploadKind(upload), path, name: upload.name } }))
|
|
380
|
+
: stickerFile
|
|
381
|
+
? onDisk(stickerFile.source, (path) => engine.sendMedia({ ...request, file: { kind: "sticker", path, name: stickerFile.name } }))
|
|
382
|
+
: engine.send(request));
|
|
383
|
+
return { message: toMessage(message), sendId: options.sendId };
|
|
384
|
+
},
|
|
385
|
+
forward: async (fromChatId, messageId, toChatId, { sendId, threadId }) => {
|
|
386
|
+
if (threadId !== undefined)
|
|
387
|
+
throw new CliError("validation_error", "WhatsApp forwards without a topic");
|
|
388
|
+
const original = await held(fromChatId, messageId);
|
|
389
|
+
const attachments = original.attachments.map(toWaAttachment);
|
|
390
|
+
const [attachment] = attachments;
|
|
391
|
+
if (attachments.length > 1 || (attachments.length === 1 && !attachment?.ref))
|
|
392
|
+
throw new CliError("validation_error", "the local store does not hold this message's content whole, so it cannot be forwarded; forward it on the phone");
|
|
393
|
+
if (!attachment && original.text === "")
|
|
394
|
+
throw new CliError("validation_error", "that message has nothing to forward");
|
|
395
|
+
// A channel's files carry no key, and a chat's recipient cannot open a file without one.
|
|
396
|
+
if (isChannel(fromChatId) && attachment?.ref && "directPath" in attachment.ref)
|
|
397
|
+
throw new CliError("validation_error", "a WhatsApp channel's file is not encrypted, so a forward would arrive as a file that does not open; " +
|
|
398
|
+
"save it on the phone and send it as a new file", { reason: "media.channel-file-forward" });
|
|
399
|
+
const copy = await translated(engine.forward({ chat: toChatId, id: sendId, text: original.text, attachment: attachment ?? null }));
|
|
400
|
+
return { ...toMessage(copy), forwardedFrom: quoted(original) };
|
|
401
|
+
},
|
|
402
|
+
// From the keys in the store: WhatsApp has no request for an old message. A file that is not one (a place, a
|
|
403
|
+
// contact card) or that the store has no keys for is named in `skipped`. The message's key goes along, so the
|
|
404
|
+
// engine can ask the phone for a file WhatsApp no longer keeps.
|
|
405
|
+
download: async (chat, messageId) => {
|
|
406
|
+
const { id: chatId } = await core.resolve(chat);
|
|
407
|
+
const message = await held(chatId, messageId);
|
|
408
|
+
const files = [];
|
|
409
|
+
const skipped = [];
|
|
410
|
+
message.attachments.forEach((stored, position) => {
|
|
411
|
+
const attachment = toWaAttachment(stored);
|
|
412
|
+
if (!isFile(attachment)) {
|
|
413
|
+
skipped.push(stored.kind);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const file = {
|
|
417
|
+
kind: attachment.kind,
|
|
418
|
+
...(attachment.name === undefined ? {} : { name: attachment.name }),
|
|
419
|
+
...(attachment.mime === undefined ? {} : { mime: attachment.mime }),
|
|
420
|
+
...(attachment.size === undefined ? {} : { size: attachment.size }),
|
|
421
|
+
position,
|
|
422
|
+
bytes: () => fetched(file, attachment, keyOf(chatId, message)),
|
|
423
|
+
};
|
|
424
|
+
files.push(file);
|
|
425
|
+
});
|
|
426
|
+
return { files, skipped };
|
|
427
|
+
},
|
|
428
|
+
edit: async (chatId, messageId, text, { markup, formatting }) => {
|
|
429
|
+
if (markup !== undefined)
|
|
430
|
+
throw new CliError("validation_error", "WhatsApp cannot edit with markup");
|
|
431
|
+
const original = await held(chatId, messageId);
|
|
432
|
+
if (!original.outgoing)
|
|
433
|
+
throw new CliError("validation_error", "only your own messages can be edited");
|
|
434
|
+
if (Date.now() - Date.parse(original.timestamp) > EDIT_WINDOW_MS)
|
|
435
|
+
throw new CliError("validation_error", "WhatsApp takes an edit only within 20 minutes of sending");
|
|
436
|
+
const edited = await translated(engine.edit(keyOf(chatId, original), formatting ? toWhatsApp(text, formatting) : text));
|
|
437
|
+
return { ...original, text: edited.text, editedAt: edited.editedAt };
|
|
438
|
+
},
|
|
439
|
+
delete: async (chatId, messageIds, { forEveryone }) => {
|
|
440
|
+
const messages = await Promise.all(messageIds.map((id) => held(chatId, id)));
|
|
441
|
+
const done = [];
|
|
442
|
+
for (const message of messages) {
|
|
443
|
+
try {
|
|
444
|
+
if (forEveryone)
|
|
445
|
+
await translated(engine.revoke(keyOf(chatId, message)));
|
|
446
|
+
else
|
|
447
|
+
await synced(engine.deleteForMe({ ...keyOf(chatId, message), timestamp: message.timestamp }));
|
|
448
|
+
}
|
|
449
|
+
catch (error) {
|
|
450
|
+
if (done.length === 0 || !(error instanceof CliError))
|
|
451
|
+
throw error;
|
|
452
|
+
// One request per message: the ones before this went, so the run as a whole is not unsent (WC-OUT-20).
|
|
453
|
+
const { sent: _, ...details } = error.details;
|
|
454
|
+
throw new CliError(error.code, `deleted ${done.join(", ")}; ${message.id} and any after it were not, or may not have been: ${error.message}`, details);
|
|
455
|
+
}
|
|
456
|
+
done.push(message.id);
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
react: async (chatId, messageId, emoji) => {
|
|
460
|
+
const message = await held(chatId, messageId);
|
|
461
|
+
await translated(engine.react(keyOf(chatId, message), emoji));
|
|
462
|
+
},
|
|
463
|
+
star: async (chatId, messageId, starred) => {
|
|
464
|
+
const message = await held(chatId, messageId);
|
|
465
|
+
await synced(engine.star(keyOf(chatId, message), starred));
|
|
466
|
+
},
|
|
467
|
+
// The read patch takes a mark-unread off the owner's devices, which a receipt does not; it is bounded by `until`
|
|
468
|
+
// or the newest stored message, either side's, so it names nothing newer than the receipt covers. It goes first,
|
|
469
|
+
// so a refusal for missing settings keys leaves nothing sent. Then one receipt, for the newest message from
|
|
470
|
+
// someone else up to `until`: the account's own messages have none. A chat the store holds nothing of has neither.
|
|
471
|
+
markRead: async (chatId, until) => {
|
|
472
|
+
const anchor = until === undefined ? await stored.anchor(chatId, AFTER_EVERY_MESSAGE) : await held(chatId, until);
|
|
473
|
+
if (!anchor)
|
|
474
|
+
return;
|
|
475
|
+
if (!isChannel(chatId) && !chatId.endsWith("@broadcast"))
|
|
476
|
+
await synced(engine.markChatRead({ ...keyOf(chatId, anchor), timestamp: anchor.timestamp }));
|
|
477
|
+
const target = until !== undefined && !anchor.outgoing ? anchor : await stored.newestIncoming(chatId, until);
|
|
478
|
+
if (target)
|
|
479
|
+
await translated(engine.markRead(keyOf(chatId, target)));
|
|
480
|
+
},
|
|
481
|
+
// `messages sync` pages back through this. WhatsApp keeps no history on its servers, so each page is asked of the
|
|
482
|
+
// phone, counting back from a message the store holds: the oldest one on the first page, then the one the last
|
|
483
|
+
// page reached (`before` is a time, `fetching.orderBy: "time"`).
|
|
484
|
+
history: async (chat, { limit, before }) => {
|
|
485
|
+
const { id: chatId } = await core.resolve(chat);
|
|
486
|
+
if (isChannel(chatId))
|
|
487
|
+
return translated(channelHistory(engine, stored, chatId, { limit, ...(before === undefined ? {} : { before }) }));
|
|
488
|
+
const anchor = await stored.anchor(chatId, before);
|
|
489
|
+
if (!anchor)
|
|
490
|
+
throw new CliError("not_found", "nothing of this chat is in the local store to count back from — the phone sends messages older than one " +
|
|
491
|
+
`the store holds; ${words("serve")} keeps the store filled`);
|
|
492
|
+
const older = await translated(engine.older({ ...keyOf(chatId, anchor), timestamp: anchor.timestamp }, Math.min(limit, OLDER_MAX)));
|
|
493
|
+
const items = older.messages.map(toMessage).sort((one, other) => one.timestamp.localeCompare(other.timestamp));
|
|
494
|
+
return { items, hasMore: older.more };
|
|
495
|
+
},
|
|
496
|
+
logout: () => {
|
|
497
|
+
loggingOut = true;
|
|
498
|
+
return translated(engine.logout());
|
|
499
|
+
},
|
|
500
|
+
close: () => engine.close(),
|
|
501
|
+
watch: async (onEvent, signal, onReady) => {
|
|
502
|
+
const live = handingOn(onEvent, signal);
|
|
503
|
+
try {
|
|
504
|
+
await translated(engine.ready(signal));
|
|
505
|
+
if (!signal.aborted)
|
|
506
|
+
onReady?.();
|
|
507
|
+
await live.done;
|
|
508
|
+
}
|
|
509
|
+
finally {
|
|
510
|
+
await live.stop();
|
|
511
|
+
}
|
|
512
|
+
},
|
|
513
|
+
// What a one-shot connection receives: WhatsApp hands a queued message to a linked device once, so it is saved
|
|
514
|
+
// here or lost. Never connects; the command's own request does that.
|
|
515
|
+
listen: async (onEvent, signal) => {
|
|
516
|
+
const live = handingOn(onEvent, signal, ownLogout);
|
|
517
|
+
try {
|
|
518
|
+
await live.done;
|
|
519
|
+
}
|
|
520
|
+
finally {
|
|
521
|
+
await live.stop();
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
// The history a one-shot connection is pushed, which WhatsApp likewise sends once. Never connects.
|
|
525
|
+
listenHistory: (onBatch, signal) => pushing(onBatch, signal, ownLogout),
|
|
526
|
+
feed: (onBatch, signal) => pushing(onBatch, signal),
|
|
527
|
+
// Only phone-form one-to-one chats can need a re-key, and in one request: cli-core waits at most 5 s for it.
|
|
528
|
+
storedChats: async (ids, recipients = []) => {
|
|
529
|
+
const phones = ids.filter((id) => PHONE_CHAT.test(id));
|
|
530
|
+
const typed = recipients.filter((id) => PHONE_CHAT.test(id));
|
|
531
|
+
if (phones.length > 0 || typed.length > 0)
|
|
532
|
+
await translated(engine.storedChats(phones, typed.length > 0 ? typed : undefined));
|
|
533
|
+
},
|
|
534
|
+
};
|
|
535
|
+
const polls = pollAdapter({ engine, stored, held, keyOf, translated });
|
|
536
|
+
const groups = groupAdapter({
|
|
537
|
+
engine,
|
|
538
|
+
resolve: core.resolve,
|
|
539
|
+
translated,
|
|
540
|
+
wroteTo: (person) => stored.wroteTo(person),
|
|
541
|
+
onDisk,
|
|
542
|
+
});
|
|
543
|
+
return {
|
|
544
|
+
...core,
|
|
545
|
+
...groups,
|
|
546
|
+
...channelAdapter({ engine, resolve: core.resolve, translated, groups }),
|
|
547
|
+
...polls,
|
|
548
|
+
...channelWrites({ ...core, ...polls }),
|
|
549
|
+
...privacyAdapter({ engine, translated }),
|
|
550
|
+
...pinAdapter({ engine, held, keyOf, translated }),
|
|
551
|
+
...settingsAdapter({ engine, translated, words, stored, keyOf, onDisk }),
|
|
552
|
+
};
|
|
553
|
+
};
|
|
554
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/adapter/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Chat, GroupCard, Message, Page } from "@wirecat/cli-core";
|
|
2
|
+
import type { MessageEditing, StoredMessages } from "@wirecat/cli-core/cli";
|
|
3
|
+
import { type WaChannel } from "../engine/channels.js";
|
|
4
|
+
import type { WhatsAppEngine } from "../engine/contract.js";
|
|
5
|
+
import type { GroupAdapter } from "./groups.js";
|
|
6
|
+
import type { PollAdapter } from "./polls.js";
|
|
7
|
+
/** WhatsApp channels are whatsmeow's newsletters, and their ids end so. */
|
|
8
|
+
export declare const isChannel: (id: string) => boolean;
|
|
9
|
+
export declare const CHANNEL_LINK: RegExp;
|
|
10
|
+
/** A channel as `chats join` answers it: only its admins post, and WhatsApp has none of a group's other switches. */
|
|
11
|
+
export declare const toChannelCard: (channel: WaChannel) => GroupCard;
|
|
12
|
+
/**
|
|
13
|
+
* A channel's posts live on WhatsApp's servers, so `messages sync` reads them there: the newest first, then back
|
|
14
|
+
* from the server id of the stored post the last page reached. Nothing stored is needed to start.
|
|
15
|
+
*/
|
|
16
|
+
export declare const channelHistory: (engine: WhatsAppEngine, stored: StoredMessages, chatId: string, { limit, before }: {
|
|
17
|
+
limit: number;
|
|
18
|
+
before?: string;
|
|
19
|
+
}) => Promise<Page<Message>>;
|
|
20
|
+
/**
|
|
21
|
+
* Only a channel's owner and admins post, and WhatsApp says the account's role only when asked, so a post asks first.
|
|
22
|
+
* The role is asked before anything is uploaded. One file per post: whatsmeow's newsletter send has no album handling.
|
|
23
|
+
*/
|
|
24
|
+
export declare const refuseChannelPost: (engine: WhatsAppEngine, translated: <T>(work: Promise<T>) => Promise<T>, chatId: string, { files, reply }: {
|
|
25
|
+
files: number;
|
|
26
|
+
reply: boolean;
|
|
27
|
+
}) => Promise<void>;
|
|
28
|
+
export interface ChannelDeps {
|
|
29
|
+
engine: WhatsAppEngine;
|
|
30
|
+
resolve: (reference: string) => Promise<Chat>;
|
|
31
|
+
translated: <T>(work: Promise<T>) => Promise<T>;
|
|
32
|
+
groups: Pick<GroupAdapter, "join" | "leave">;
|
|
33
|
+
}
|
|
34
|
+
/** `chats join` and `chats leave` follow and unfollow a channel; a group's link or id goes on to the group's. */
|
|
35
|
+
export declare const channelAdapter: ({ engine, resolve, translated, groups, }: ChannelDeps) => Pick<GroupAdapter, "join" | "leave">;
|
|
36
|
+
type ChannelWrites = Pick<MessageEditing, "edit" | "delete" | "forward"> & Pick<PollAdapter, "createPoll" | "vote">;
|
|
37
|
+
/**
|
|
38
|
+
* The writes wa has not built for a channel are refused before anything is sent: whatsmeow would send each of them
|
|
39
|
+
* to a channel as a post, and WhatsApp addresses a post's edit, deletion and votes by its server id.
|
|
40
|
+
*/
|
|
41
|
+
export declare const channelWrites: ({ edit, delete: remove, forward, createPoll, vote }: ChannelWrites) => ChannelWrites;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=channels.d.ts.map
|