@wirecat/whatsapp-cli 0.0.0-stage → 0.1.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 +282 -2
- package/dist/adapter/adapter.d.ts +9 -0
- package/dist/adapter/adapter.d.ts.map +1 -0
- package/dist/adapter/adapter.js +326 -0
- package/dist/adapter/adapter.js.map +1 -0
- package/dist/adapter/checks.d.ts +7 -0
- package/dist/adapter/checks.d.ts.map +1 -0
- package/dist/adapter/checks.js +3 -0
- package/dist/adapter/checks.js.map +1 -0
- package/dist/adapter/errors.d.ts +18 -0
- package/dist/adapter/errors.d.ts.map +1 -0
- package/dist/adapter/errors.js +40 -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 +21 -0
- package/dist/adapter/groups.d.ts.map +1 -0
- package/dist/adapter/groups.js +210 -0
- package/dist/adapter/groups.js.map +1 -0
- package/dist/adapter/map.d.ts +9 -0
- package/dist/adapter/map.d.ts.map +1 -0
- package/dist/adapter/map.js +72 -0
- package/dist/adapter/map.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/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 +27 -0
- package/dist/bin/wa.js.map +1 -0
- package/dist/commands/answer.d.ts +7 -0
- package/dist/commands/answer.d.ts.map +1 -0
- package/dist/commands/answer.js +11 -0
- package/dist/commands/answer.js.map +1 -0
- package/dist/commands/session.d.ts +37 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +202 -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 +192 -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 +36 -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/contract.d.ts +617 -0
- package/dist/engine/contract.d.ts.map +1 -0
- package/dist/engine/contract.js +186 -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 +238 -0
- package/dist/engine/go-engine.js.map +1 -0
- package/dist/engine/groups.d.ts +159 -0
- package/dist/engine/groups.d.ts.map +1 -0
- package/dist/engine/groups.js +64 -0
- package/dist/engine/groups.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 +62 -0
- package/dist/install/postinstall.js.map +1 -0
- package/dist/messenger.d.ts +64 -0
- package/dist/messenger.d.ts.map +1 -0
- package/dist/messenger.js +171 -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 +8 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +114 -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 +13 -0
- package/dist/reasons.js.map +1 -0
- package/dist/update.d.ts +8 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +26 -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 +290 -0
|
@@ -0,0 +1,326 @@
|
|
|
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 { parseMarkdownSpans, } from "@wirecat/cli-core";
|
|
8
|
+
import { EngineError, OLDER_MAX, } from "../engine/contract.js";
|
|
9
|
+
import { bareCheck } from "./checks.js";
|
|
10
|
+
import { fromEngine } from "./errors.js";
|
|
11
|
+
import { toWhatsApp } from "./format-markdown.js";
|
|
12
|
+
import { groupAdapter } from "./groups.js";
|
|
13
|
+
import { toChat, toMember, toMessage, toWaAttachment } from "./map.js";
|
|
14
|
+
import { pollAdapter, toHistoryVote, toVoteEvent } from "./polls.js";
|
|
15
|
+
// WhatsApp addresses a message by its sender and by whether it is the account's own, and the engine keeps no
|
|
16
|
+
// messages, so an edit, a deletion, a reaction or a read receipt looks the message up in cli-core's store first.
|
|
17
|
+
const NOTHING_STORED = {
|
|
18
|
+
message: async () => undefined,
|
|
19
|
+
newestIncoming: async () => undefined,
|
|
20
|
+
anchor: async () => undefined,
|
|
21
|
+
wroteTo: async () => false,
|
|
22
|
+
pollVotes: async () => [],
|
|
23
|
+
};
|
|
24
|
+
// whatsmeow's EditWindow: WhatsApp clients ignore an edit that comes later.
|
|
25
|
+
const EDIT_WINDOW_MS = 20 * 60 * 1000;
|
|
26
|
+
/** Options WhatsApp has no way to honour; `noPreview` is always true, since nothing here builds link previews. */
|
|
27
|
+
const REFUSED = ["threadId", "markup", "sticker", "spoiler", "captionAbove"];
|
|
28
|
+
const translated = async (work) => {
|
|
29
|
+
try {
|
|
30
|
+
return await work;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error instanceof EngineError)
|
|
34
|
+
throw fromEngine(error);
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const hit = (chat, message) => ({ ...message, chatTitle: chat?.name ?? null });
|
|
39
|
+
const ENDED = {
|
|
40
|
+
logged_out: (words) => fromEngine(new EngineError("authentication_error", `WhatsApp logged this device out — log in again with ${words("session.start")}`, "device.logged-out")),
|
|
41
|
+
replaced: () => fromEngine(new EngineError("provider_unavailable", "another process took over this WhatsApp login; only one may hold it", "device.replaced")),
|
|
42
|
+
banned: () => fromEngine(new EngineError("permission_error", "WhatsApp has banned or restricted this account; see the phone", "account.banned")),
|
|
43
|
+
outdated: () => fromEngine(new EngineError("provider_unavailable", "WhatsApp no longer accepts this version of wa; update it", "client.outdated")),
|
|
44
|
+
stopped: () => fromEngine(new EngineError("provider_unavailable", "the WhatsApp engine stopped unexpectedly", "engine.stopped")),
|
|
45
|
+
};
|
|
46
|
+
/** Hands each event on until `signal` aborts; a connection WhatsApp ended rejects with why. */
|
|
47
|
+
const listening = (engine, kinds, signal, words, onEvent) => {
|
|
48
|
+
let stop = () => { };
|
|
49
|
+
const done = new Promise((resolve, reject) => {
|
|
50
|
+
const unlisten = engine.listen(kinds, (event) => {
|
|
51
|
+
const ended = event.event === "connection" ? ENDED[event.state]?.(words) : undefined;
|
|
52
|
+
if (ended)
|
|
53
|
+
reject(ended);
|
|
54
|
+
else
|
|
55
|
+
onEvent(event);
|
|
56
|
+
});
|
|
57
|
+
const aborted = () => resolve();
|
|
58
|
+
signal.addEventListener("abort", aborted, { once: true });
|
|
59
|
+
stop = () => {
|
|
60
|
+
unlisten();
|
|
61
|
+
signal.removeEventListener("abort", aborted);
|
|
62
|
+
};
|
|
63
|
+
if (signal.aborted)
|
|
64
|
+
resolve();
|
|
65
|
+
});
|
|
66
|
+
return { done, stop };
|
|
67
|
+
};
|
|
68
|
+
const VIDEO = new Set([".mp4", ".m4v", ".mov"]);
|
|
69
|
+
/** 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. */
|
|
70
|
+
const uploadKind = ({ kind, name, asFile }) => kind === "photo" || kind === "voice" ? kind : !asFile && VIDEO.has(extname(name).toLowerCase()) ? "video" : "document";
|
|
71
|
+
/** A folder only this user can read, gone when `work` ends: the engine writes a download into it, or reads bytes made in memory. */
|
|
72
|
+
const inPrivateFolder = async (work) => {
|
|
73
|
+
const folder = await mkdtemp(join(tmpdir(), "wa-media-"));
|
|
74
|
+
try {
|
|
75
|
+
return await work(folder);
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
await rm(folder, { recursive: true, force: true });
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const onDisk = async (source, work) => {
|
|
82
|
+
if (source.kind === "file")
|
|
83
|
+
return work(absolute(source.path));
|
|
84
|
+
return inPrivateFolder(async (folder) => {
|
|
85
|
+
const path = join(folder, "upload");
|
|
86
|
+
await writeFile(path, source.bytes, { mode: 0o600, flag: "wx" });
|
|
87
|
+
return work(path);
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
const quoted = (message) => ({
|
|
91
|
+
id: message.id,
|
|
92
|
+
senderId: message.senderId,
|
|
93
|
+
senderName: message.senderName,
|
|
94
|
+
timestamp: message.timestamp,
|
|
95
|
+
text: message.text,
|
|
96
|
+
attachments: message.attachments,
|
|
97
|
+
outgoing: message.outgoing ?? null,
|
|
98
|
+
});
|
|
99
|
+
const keyOf = (chatId, message) => ({
|
|
100
|
+
chat: chatId,
|
|
101
|
+
id: message.id,
|
|
102
|
+
fromMe: message.outgoing === true,
|
|
103
|
+
sender: message.senderId,
|
|
104
|
+
});
|
|
105
|
+
export const whatsAppAdapter = (engine, stored = NOTHING_STORED, words = bareCheck) => {
|
|
106
|
+
// A guessed key would make WhatsApp drop the change without a word, so a message the store lacks is refused.
|
|
107
|
+
const held = async (chatId, messageId) => {
|
|
108
|
+
const message = await stored.message(chatId, messageId);
|
|
109
|
+
if (!message)
|
|
110
|
+
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`);
|
|
111
|
+
return message;
|
|
112
|
+
};
|
|
113
|
+
async function* fetched(attachment) {
|
|
114
|
+
const folder = await mkdtemp(join(tmpdir(), "wa-media-"));
|
|
115
|
+
try {
|
|
116
|
+
const path = join(folder, "file");
|
|
117
|
+
await translated(engine.download(attachment, path));
|
|
118
|
+
yield* createReadStream(path);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
await rm(folder, { recursive: true, force: true });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const titled = async () => new Map((await translated(engine.directory())).map((chat) => [chat.jid, chat]));
|
|
125
|
+
const core = {
|
|
126
|
+
formatMarkdown: async (text) => parseMarkdownSpans(text),
|
|
127
|
+
self: () => engine.self(),
|
|
128
|
+
newSendId: () => `3EB0${randomBytes(9).toString("hex").toUpperCase()}`,
|
|
129
|
+
me: async () => {
|
|
130
|
+
const account = await translated(engine.me());
|
|
131
|
+
return { id: account.jid, name: account.name, username: null };
|
|
132
|
+
},
|
|
133
|
+
resolve: async (query) => {
|
|
134
|
+
const chats = await titled();
|
|
135
|
+
const byId = chats.get(query);
|
|
136
|
+
if (byId)
|
|
137
|
+
return toChat(byId);
|
|
138
|
+
if (query.includes("@"))
|
|
139
|
+
return {
|
|
140
|
+
id: query,
|
|
141
|
+
title: null,
|
|
142
|
+
kind: "unknown",
|
|
143
|
+
unreadCount: null,
|
|
144
|
+
lastMessageAt: null,
|
|
145
|
+
participantsCount: null,
|
|
146
|
+
};
|
|
147
|
+
const named = [...chats.values()].filter((chat) => chat.name === query);
|
|
148
|
+
if (named.length === 1 && named[0])
|
|
149
|
+
return toChat(named[0]);
|
|
150
|
+
if (named.length > 1)
|
|
151
|
+
throw new CliError("validation_error", `${named.length} chats share that name — name one by its id; ${words("chats.list")} shows them`);
|
|
152
|
+
throw new CliError("not_found", `no chat by that name or id; ${words("chats.list")} shows the chats this profile has`);
|
|
153
|
+
},
|
|
154
|
+
chat: async (jid) => {
|
|
155
|
+
const card = await translated(engine.chat(jid));
|
|
156
|
+
return { ...toChat(card.chat), members: card.members?.map(toMember) ?? null };
|
|
157
|
+
},
|
|
158
|
+
send: async (chatId, text, options) => {
|
|
159
|
+
const refused = REFUSED.filter((option) => options[option] !== undefined && options[option] !== false);
|
|
160
|
+
if (refused.length > 0)
|
|
161
|
+
throw new CliError("validation_error", `WhatsApp cannot send with ${refused.join(", ")}`);
|
|
162
|
+
const [upload, ...more] = options.attachments ?? [];
|
|
163
|
+
if (more.length > 0)
|
|
164
|
+
throw new CliError("validation_error", "WhatsApp sends one file per message here");
|
|
165
|
+
if (upload?.kind === "voice" && text.trim() !== "")
|
|
166
|
+
throw new CliError("validation_error", "WhatsApp sends a voice message alone, without text");
|
|
167
|
+
// A reply to a message the store lacks still goes, with its id alone.
|
|
168
|
+
const answered = options.replyTo === undefined ? undefined : await stored.message(chatId, options.replyTo);
|
|
169
|
+
const request = {
|
|
170
|
+
chat: chatId,
|
|
171
|
+
text: options.formatting ? toWhatsApp(text, options.formatting) : text,
|
|
172
|
+
id: options.sendId,
|
|
173
|
+
...(options.replyTo === undefined ? {} : { replyTo: options.replyTo }),
|
|
174
|
+
...(answered
|
|
175
|
+
? { quoted: { fromMe: answered.outgoing === true, sender: answered.senderId, text: answered.text } }
|
|
176
|
+
: {}),
|
|
177
|
+
};
|
|
178
|
+
const message = await translated(upload
|
|
179
|
+
? onDisk(upload.source, (path) => engine.sendMedia({ ...request, file: { kind: uploadKind(upload), path, name: upload.name } }))
|
|
180
|
+
: engine.send(request));
|
|
181
|
+
return { message: toMessage(message), sendId: options.sendId };
|
|
182
|
+
},
|
|
183
|
+
forward: async (fromChatId, messageId, toChatId, { sendId, threadId }) => {
|
|
184
|
+
if (threadId !== undefined)
|
|
185
|
+
throw new CliError("validation_error", "WhatsApp forwards without a topic");
|
|
186
|
+
const original = await held(fromChatId, messageId);
|
|
187
|
+
const attachments = original.attachments.map(toWaAttachment);
|
|
188
|
+
const [attachment] = attachments;
|
|
189
|
+
if (attachments.length > 1 || (attachments.length === 1 && !attachment?.ref))
|
|
190
|
+
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");
|
|
191
|
+
if (!attachment && original.text === "")
|
|
192
|
+
throw new CliError("validation_error", "that message has nothing to forward");
|
|
193
|
+
const copy = await translated(engine.forward({ chat: toChatId, id: sendId, text: original.text, attachment: attachment ?? null }));
|
|
194
|
+
return { ...toMessage(copy), forwardedFrom: quoted(original) };
|
|
195
|
+
},
|
|
196
|
+
// From the keys in the store: WhatsApp has no request for an old message. A file that is not one (a place, a
|
|
197
|
+
// contact card) or that the store has no keys for is named in `skipped`.
|
|
198
|
+
download: async (chat, messageId) => {
|
|
199
|
+
const { id: chatId } = await core.resolve(chat);
|
|
200
|
+
const message = await held(chatId, messageId);
|
|
201
|
+
const files = [];
|
|
202
|
+
const skipped = [];
|
|
203
|
+
message.attachments.forEach((stored, position) => {
|
|
204
|
+
const attachment = toWaAttachment(stored);
|
|
205
|
+
if (!attachment?.ref) {
|
|
206
|
+
skipped.push(stored.kind);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
files.push({
|
|
210
|
+
kind: attachment.kind,
|
|
211
|
+
...(attachment.name === undefined ? {} : { name: attachment.name }),
|
|
212
|
+
...(attachment.mime === undefined ? {} : { mime: attachment.mime }),
|
|
213
|
+
...(attachment.size === undefined ? {} : { size: attachment.size }),
|
|
214
|
+
position,
|
|
215
|
+
bytes: () => fetched(attachment),
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
return { files, skipped };
|
|
219
|
+
},
|
|
220
|
+
edit: async (chatId, messageId, text, { markup, formatting }) => {
|
|
221
|
+
if (markup !== undefined)
|
|
222
|
+
throw new CliError("validation_error", "WhatsApp cannot edit with markup");
|
|
223
|
+
const original = await held(chatId, messageId);
|
|
224
|
+
if (!original.outgoing)
|
|
225
|
+
throw new CliError("validation_error", "only your own messages can be edited");
|
|
226
|
+
if (Date.now() - Date.parse(original.timestamp) > EDIT_WINDOW_MS)
|
|
227
|
+
throw new CliError("validation_error", "WhatsApp takes an edit only within 20 minutes of sending");
|
|
228
|
+
const edited = await translated(engine.edit(keyOf(chatId, original), formatting ? toWhatsApp(text, formatting) : text));
|
|
229
|
+
return { ...original, text: edited.text, editedAt: edited.editedAt };
|
|
230
|
+
},
|
|
231
|
+
delete: async (chatId, messageIds, { forEveryone }) => {
|
|
232
|
+
if (!forEveryone)
|
|
233
|
+
throw new CliError("validation_error", "wa deletes only for everyone so far; add --for-everyone, or delete it for you on the phone");
|
|
234
|
+
const messages = await Promise.all(messageIds.map((id) => held(chatId, id)));
|
|
235
|
+
for (const message of messages)
|
|
236
|
+
await translated(engine.revoke(keyOf(chatId, message)));
|
|
237
|
+
},
|
|
238
|
+
react: async (chatId, messageId, emoji) => {
|
|
239
|
+
const message = await held(chatId, messageId);
|
|
240
|
+
await translated(engine.react(keyOf(chatId, message), emoji));
|
|
241
|
+
},
|
|
242
|
+
// One receipt, for the newest message from someone else up to `until`: the account's own messages have none.
|
|
243
|
+
markRead: async (chatId, until) => {
|
|
244
|
+
const anchor = until === undefined ? undefined : await held(chatId, until);
|
|
245
|
+
const target = anchor && !anchor.outgoing ? anchor : await stored.newestIncoming(chatId, until);
|
|
246
|
+
if (target)
|
|
247
|
+
await translated(engine.markRead(keyOf(chatId, target)));
|
|
248
|
+
},
|
|
249
|
+
// `messages sync` pages back through this. WhatsApp keeps no history on its servers, so each page is asked of the
|
|
250
|
+
// phone, counting back from a message the store holds: the oldest one on the first page, then the one the last
|
|
251
|
+
// page reached (`before` is a time, `fetching.orderBy: "time"`).
|
|
252
|
+
history: async (chat, { limit, before }) => {
|
|
253
|
+
const { id: chatId } = await core.resolve(chat);
|
|
254
|
+
const anchor = await stored.anchor(chatId, before);
|
|
255
|
+
if (!anchor)
|
|
256
|
+
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 " +
|
|
257
|
+
`the store holds; ${words("serve")} keeps the store filled`);
|
|
258
|
+
const older = await translated(engine.older({ ...keyOf(chatId, anchor), timestamp: anchor.timestamp }, Math.min(limit, OLDER_MAX)));
|
|
259
|
+
const items = older.messages.map(toMessage).sort((one, other) => one.timestamp.localeCompare(other.timestamp));
|
|
260
|
+
return { items, hasMore: older.more };
|
|
261
|
+
},
|
|
262
|
+
logout: () => translated(engine.logout()),
|
|
263
|
+
close: () => engine.close(),
|
|
264
|
+
watch: async (onEvent, signal, onReady) => {
|
|
265
|
+
const chats = await titled();
|
|
266
|
+
const handed = async (event) => {
|
|
267
|
+
if (event.event === "message")
|
|
268
|
+
onEvent({ event: "message", message: hit(chats.get(event.message.chat), toMessage(event.message)) });
|
|
269
|
+
else if (event.event === "edit")
|
|
270
|
+
onEvent({ event: "edit", message: hit(chats.get(event.message.chat), toMessage(event.message)) });
|
|
271
|
+
else if (event.event === "delete")
|
|
272
|
+
onEvent({
|
|
273
|
+
event: "delete",
|
|
274
|
+
chatId: event.chat,
|
|
275
|
+
chatTitle: chats.get(event.chat)?.name ?? null,
|
|
276
|
+
messageId: event.id,
|
|
277
|
+
});
|
|
278
|
+
else if (event.event === "vote") {
|
|
279
|
+
const vote = await toVoteEvent(event.vote, chats.get(event.vote.chat)?.name ?? null, stored);
|
|
280
|
+
if (vote)
|
|
281
|
+
onEvent(vote);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
// In arrival order: a vote reads its poll from the store, and nothing after it may overtake it.
|
|
285
|
+
let queue = Promise.resolve();
|
|
286
|
+
const live = listening(engine, ["message", "edit", "delete", "vote", "connection"], signal, words, (event) => {
|
|
287
|
+
queue = queue.then(() => handed(event));
|
|
288
|
+
});
|
|
289
|
+
try {
|
|
290
|
+
await translated(engine.ready(signal));
|
|
291
|
+
if (!signal.aborted)
|
|
292
|
+
onReady?.();
|
|
293
|
+
await live.done;
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
live.stop();
|
|
297
|
+
await queue;
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
feed: async (onBatch, signal) => {
|
|
301
|
+
const pushes = listening(engine, ["history", "connection"], signal, words, (event) => {
|
|
302
|
+
if (event.event !== "history")
|
|
303
|
+
return;
|
|
304
|
+
const { chats, contacts, messages, votes } = event.history;
|
|
305
|
+
onBatch({
|
|
306
|
+
chats: chats.map(toChat),
|
|
307
|
+
people: contacts.map(toMember),
|
|
308
|
+
messages: messages.map(toMessage),
|
|
309
|
+
votes: votes.flatMap((vote) => toHistoryVote(vote) ?? []),
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
try {
|
|
313
|
+
await pushes.done;
|
|
314
|
+
}
|
|
315
|
+
finally {
|
|
316
|
+
pushes.stop();
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
return {
|
|
321
|
+
...core,
|
|
322
|
+
...groupAdapter({ engine, resolve: core.resolve, translated, wroteTo: (person) => stored.wroteTo(person) }),
|
|
323
|
+
...pollAdapter({ engine, stored, held, keyOf, translated }),
|
|
324
|
+
};
|
|
325
|
+
};
|
|
326
|
+
//# 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,7 @@
|
|
|
1
|
+
/** The commands a message sends a person to; the command layer names them in its own words. */
|
|
2
|
+
export type Check = "chats.list" | "serve" | "session.start";
|
|
3
|
+
/** A command as the person types it, in one pair of backticks. */
|
|
4
|
+
export type Words = (check: Check) => string;
|
|
5
|
+
/** Without the command layer's words, a check is named by its command path alone. */
|
|
6
|
+
export declare const bareCheck: Words;
|
|
7
|
+
//# sourceMappingURL=checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/adapter/checks.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,MAAM,MAAM,KAAK,GAAG,YAAY,GAAG,OAAO,GAAG,eAAe,CAAA;AAE5D,kEAAkE;AAClE,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAA;AAE5C,qFAAqF;AACrF,eAAO,MAAM,SAAS,EAAE,KAAsD,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/adapter/checks.ts"],"names":[],"mappings":"AAMA,qFAAqF;AACrF,MAAM,CAAC,MAAM,SAAS,GAAU,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
import type { EngineError } from "../engine/contract.js";
|
|
3
|
+
/**
|
|
4
|
+
* WhatsApp's 429 says neither how long nor whether reads count, so writes wait this long and reads go on
|
|
5
|
+
* (WC-PERM-18). The owner's to change: docs/dev/BACKLOG.md.
|
|
6
|
+
*/
|
|
7
|
+
export declare const RATE_LIMIT_HOLD_MS: number;
|
|
8
|
+
/**
|
|
9
|
+
* A ban says nothing about the account's standing, so writes stay held until `doctor --online` connects again. cli-core
|
|
10
|
+
* keeps no hold without an end, so the end is set past any ban WhatsApp gives.
|
|
11
|
+
*/
|
|
12
|
+
export declare const BAN_HOLD_MS: number;
|
|
13
|
+
/**
|
|
14
|
+
* An engine refusal in cli-core's terms, its reason kept. A rate limit and a ban carry `standing`, which cli-core turns
|
|
15
|
+
* into a hold on the profile's writes.
|
|
16
|
+
*/
|
|
17
|
+
export declare const fromEngine: (error: EngineError, now?: number) => CliError;
|
|
18
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/adapter/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAc,CAAA;AAC7C;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAyB,CAAA;AAIjD;;;GAGG;AACH,eAAO,MAAM,UAAU,UAAW,WAAW,mBAAqB,QAsBjE,CAAA"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
/**
|
|
3
|
+
* WhatsApp's 429 says neither how long nor whether reads count, so writes wait this long and reads go on
|
|
4
|
+
* (WC-PERM-18). The owner's to change: docs/dev/BACKLOG.md.
|
|
5
|
+
*/
|
|
6
|
+
export const RATE_LIMIT_HOLD_MS = 15 * 60_000;
|
|
7
|
+
/**
|
|
8
|
+
* A ban says nothing about the account's standing, so writes stay held until `doctor --online` connects again. cli-core
|
|
9
|
+
* keeps no hold without an end, so the end is set past any ban WhatsApp gives.
|
|
10
|
+
*/
|
|
11
|
+
export const BAN_HOLD_MS = 365 * 24 * 60 * 60_000;
|
|
12
|
+
const at = (ms) => new Date(ms).toISOString();
|
|
13
|
+
/**
|
|
14
|
+
* An engine refusal in cli-core's terms, its reason kept. A rate limit and a ban carry `standing`, which cli-core turns
|
|
15
|
+
* into a hold on the profile's writes.
|
|
16
|
+
*/
|
|
17
|
+
export const fromEngine = (error, now = Date.now()) => {
|
|
18
|
+
const reason = error.reason === undefined ? {} : { reason: error.reason };
|
|
19
|
+
if (error.reason === "account.rate-limited")
|
|
20
|
+
return new CliError(error.code, `${error.message}; this profile holds its writes for 15 minutes`, {
|
|
21
|
+
...reason,
|
|
22
|
+
retry_after_ms: RATE_LIMIT_HOLD_MS,
|
|
23
|
+
standing: {
|
|
24
|
+
state: "limited",
|
|
25
|
+
hint: "WhatsApp asked this account to slow down",
|
|
26
|
+
until: at(now + RATE_LIMIT_HOLD_MS),
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
if (error.reason === "account.banned")
|
|
30
|
+
return new CliError(error.code, error.message, {
|
|
31
|
+
...reason,
|
|
32
|
+
standing: {
|
|
33
|
+
state: "frozen",
|
|
34
|
+
hint: "WhatsApp banned or restricted this account",
|
|
35
|
+
until: at(now + BAN_HOLD_MS),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
return new CliError(error.code, error.message, reason);
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/adapter/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAI5C;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,GAAG,MAAM,CAAA;AAC7C;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,CAAA;AAEjD,MAAM,EAAE,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;AAErD;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAkB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAY,EAAE;IAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAA;IACzE,IAAI,KAAK,CAAC,MAAM,KAAK,sBAAsB;QACzC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,OAAO,gDAAgD,EAAE;YAChG,GAAG,MAAM;YACT,cAAc,EAAE,kBAAkB;YAClC,QAAQ,EAAE;gBACR,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,0CAA0C;gBAChD,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,kBAAkB,CAAC;aACV;SAC5B,CAAC,CAAA;IACJ,IAAI,KAAK,CAAC,MAAM,KAAK,gBAAgB;QACnC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE;YAC7C,GAAG,MAAM;YACT,QAAQ,EAAE;gBACR,KAAK,EAAE,QAAQ;gBACf,IAAI,EAAE,4CAA4C;gBAClD,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,WAAW,CAAC;aACH;SAC5B,CAAC,CAAA;IACJ,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AACxD,CAAC,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TextSpan } from "@wirecat/cli-core";
|
|
2
|
+
/**
|
|
3
|
+
* Text and its spans in WhatsApp's marks: `*bold*`, `_italic_`, `~strike~`, `` `code` ``, ```` ``` ```` blocks and
|
|
4
|
+
* `> ` quotes. A link is its label and then its address, which WhatsApp makes clickable. Underline, spoiler and
|
|
5
|
+
* highlight have no mark there and stay plain text, and a span that crosses another without nesting is dropped.
|
|
6
|
+
*/
|
|
7
|
+
export declare const toWhatsApp: (text: string, spans: readonly TextSpan[]) => string;
|
|
8
|
+
//# sourceMappingURL=format-markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-markdown.d.ts","sourceRoot":"","sources":["../../src/adapter/format-markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAiDjD;;;;GAIG;AACH,eAAO,MAAM,UAAU,SAAU,MAAM,SAAS,SAAS,QAAQ,EAAE,KAAG,MA6BrE,CAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const MARKS = {
|
|
2
|
+
bold: "*",
|
|
3
|
+
heading: "*",
|
|
4
|
+
italic: "_",
|
|
5
|
+
strike: "~",
|
|
6
|
+
code: "`",
|
|
7
|
+
pre: "```",
|
|
8
|
+
};
|
|
9
|
+
// WhatsApp draws these on one line only.
|
|
10
|
+
const LINE_ONLY = new Set(["bold", "heading", "italic", "strike", "code"]);
|
|
11
|
+
/** WhatsApp ignores a mark with a space just inside it, so the space moves outside. */
|
|
12
|
+
const trimmed = (text, span, from, to) => {
|
|
13
|
+
// A code block's indentation is part of the code.
|
|
14
|
+
while (from < to && span.type !== "pre" && /\s/u.test(text[from] ?? ""))
|
|
15
|
+
from++;
|
|
16
|
+
while (to > from && /\s/u.test(text[to - 1] ?? ""))
|
|
17
|
+
to--;
|
|
18
|
+
return to > from ? { ...span, from, length: to - from } : undefined;
|
|
19
|
+
};
|
|
20
|
+
const perLine = (text, span) => {
|
|
21
|
+
const end = span.from + span.length;
|
|
22
|
+
if (!LINE_ONLY.has(span.type)) {
|
|
23
|
+
const whole = trimmed(text, span, span.from, end);
|
|
24
|
+
return whole ? [whole] : [];
|
|
25
|
+
}
|
|
26
|
+
const pieces = [];
|
|
27
|
+
for (let start = span.from; start < end;) {
|
|
28
|
+
const newline = text.indexOf("\n", start);
|
|
29
|
+
const stop = newline === -1 || newline >= end ? end : newline;
|
|
30
|
+
const piece = trimmed(text, span, start, stop);
|
|
31
|
+
if (piece)
|
|
32
|
+
pieces.push(piece);
|
|
33
|
+
start = stop + 1;
|
|
34
|
+
}
|
|
35
|
+
return pieces;
|
|
36
|
+
};
|
|
37
|
+
const contains = (outer, inner) => outer.from <= inner.from && inner.from + inner.length <= outer.from + outer.length;
|
|
38
|
+
const apart = (a, b) => a.from + a.length <= b.from || b.from + b.length <= a.from;
|
|
39
|
+
const linkTail = (text, span) => {
|
|
40
|
+
const label = text.slice(span.from, span.from + span.length);
|
|
41
|
+
return span.url === undefined || span.url === label || span.url === `mailto:${label}` ? "" : ` (${span.url})`;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Text and its spans in WhatsApp's marks: `*bold*`, `_italic_`, `~strike~`, `` `code` ``, ```` ``` ```` blocks and
|
|
45
|
+
* `> ` quotes. A link is its label and then its address, which WhatsApp makes clickable. Underline, spoiler and
|
|
46
|
+
* highlight have no mark there and stay plain text, and a span that crosses another without nesting is dropped.
|
|
47
|
+
*/
|
|
48
|
+
export const toWhatsApp = (text, spans) => {
|
|
49
|
+
const kept = [];
|
|
50
|
+
const ordered = spans
|
|
51
|
+
.flatMap((span) => perLine(text, span))
|
|
52
|
+
.sort((a, b) => a.from - b.from || b.length - a.length || a.type.localeCompare(b.type));
|
|
53
|
+
for (const span of ordered)
|
|
54
|
+
if (kept.every((one) => contains(one, span) || apart(one, span)))
|
|
55
|
+
kept.push(span);
|
|
56
|
+
let out = "";
|
|
57
|
+
const open = [];
|
|
58
|
+
let next = 0;
|
|
59
|
+
for (let at = 0; at <= text.length; at++) {
|
|
60
|
+
for (let top = open.at(-1); top && top.from + top.length === at; top = open.at(-1)) {
|
|
61
|
+
open.pop();
|
|
62
|
+
out += top.type === "link" ? linkTail(text, top) : (MARKS[top.type] ?? "");
|
|
63
|
+
}
|
|
64
|
+
for (; kept[next]?.from === at; next++) {
|
|
65
|
+
const span = kept[next];
|
|
66
|
+
open.push(span);
|
|
67
|
+
out += span.type === "blockquote" ? "> " : (MARKS[span.type] ?? "");
|
|
68
|
+
}
|
|
69
|
+
if (at === text.length)
|
|
70
|
+
break;
|
|
71
|
+
out += text[at];
|
|
72
|
+
if (text[at] === "\n")
|
|
73
|
+
out += open
|
|
74
|
+
.filter((span) => span.type === "blockquote")
|
|
75
|
+
.map(() => "> ")
|
|
76
|
+
.join("");
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=format-markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-markdown.js","sourceRoot":"","sources":["../../src/adapter/format-markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Chat, GroupCard } from "@wirecat/cli-core";
|
|
2
|
+
import type { MessengerAdapter } from "@wirecat/cli-core/cli";
|
|
3
|
+
import type { WhatsAppEngine } from "../engine/contract.js";
|
|
4
|
+
import type { WaGroup } from "../engine/groups.js";
|
|
5
|
+
/** Group moderation and admin, join requests, profiles, blocking, number lookup and the account's health. */
|
|
6
|
+
export type GroupAdapter = Required<Pick<MessengerAdapter, "members" | "admins" | "people" | "createGroup" | "join" | "leave" | "group" | "updateGroup" | "resetInviteLink" | "addMembers" | "removeMembers" | "addAdmin" | "removeAdmin" | "joinRequests" | "answerJoinRequest" | "profile" | "block" | "unblock" | "lookup" | "addressBook" | "health">>;
|
|
7
|
+
/** What a WhatsApp admin may do. WhatsApp has one kind of admin, with all of these at once. */
|
|
8
|
+
export declare const ADMIN_RIGHTS: ["members", "admins", "info", "pin", "link", "post", "delete"];
|
|
9
|
+
/** The switches of cli-core's `chats update` that WhatsApp has. */
|
|
10
|
+
export declare const GROUP_SETTINGS: readonly ["onlyAdminsAdd", "joinApproval", "onlyAdminsSend", "onlyAdminsEditInfo", "disappearingSeconds"];
|
|
11
|
+
/** A group as `chats update` and `chats create` answer it. */
|
|
12
|
+
export declare const toGroupCard: (group: WaGroup) => GroupCard;
|
|
13
|
+
export interface GroupDeps {
|
|
14
|
+
engine: WhatsAppEngine;
|
|
15
|
+
resolve: (reference: string) => Promise<Chat>;
|
|
16
|
+
translated: <T>(work: Promise<T>) => Promise<T>;
|
|
17
|
+
/** Whether the owner has written to this person; from cli-core's store. */
|
|
18
|
+
wroteTo: (personId: string) => Promise<boolean>;
|
|
19
|
+
}
|
|
20
|
+
export declare const groupAdapter: ({ engine, resolve, translated, wroteTo }: GroupDeps) => GroupAdapter;
|
|
21
|
+
//# sourceMappingURL=groups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../src/adapter/groups.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,IAAI,EAAE,SAAS,EAA6B,MAAM,mBAAmB,CAAA;AAC/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,6GAA6G;AAC7G,MAAM,MAAM,YAAY,GAAG,QAAQ,CACjC,IAAI,CACF,gBAAgB,EACd,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,aAAa,GACb,MAAM,GACN,OAAO,GACP,OAAO,GACP,aAAa,GACb,iBAAiB,GACjB,YAAY,GACZ,eAAe,GACf,UAAU,GACV,aAAa,GACb,cAAc,GACd,mBAAmB,GACnB,SAAS,GACT,OAAO,GACP,SAAS,GACT,QAAQ,GACR,aAAa,GACb,QAAQ,CACX,CACF,CAAA;AAED,+FAA+F;AAC/F,eAAO,MAAM,YAAY,gEAQQ,CAAA;AAEjC,mEAAmE;AACnE,eAAO,MAAM,cAAc,YACzB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,CACb,CAAA;AAOV,8DAA8D;AAC9D,eAAO,MAAM,WAAW,UAAW,OAAO,KAAG,SAkB5C,CAAA;AASD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,UAAU,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;IAC/C,2EAA2E;IAC3E,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAChD;AAED,eAAO,MAAM,YAAY,6CAA8C,SAAS,KAAG,YAuLlF,CAAA"}
|