@wirecat/whatsapp-cli 0.4.0 → 0.6.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/README.md +3 -0
- package/dist/adapter/adapter.d.ts +1 -1
- package/dist/adapter/adapter.d.ts.map +1 -1
- package/dist/adapter/adapter.js +16 -406
- package/dist/adapter/adapter.js.map +1 -1
- package/dist/adapter/channels.d.ts.map +1 -1
- package/dist/adapter/channels.js.map +1 -1
- package/dist/adapter/errors.d.ts +1 -1
- package/dist/adapter/errors.d.ts.map +1 -1
- package/dist/adapter/errors.js +4 -2
- package/dist/adapter/errors.js.map +1 -1
- package/dist/adapter/groups.d.ts.map +1 -1
- package/dist/adapter/groups.js +1 -1
- package/dist/adapter/groups.js.map +1 -1
- package/dist/adapter/listen.d.ts +11 -0
- package/dist/adapter/listen.d.ts.map +1 -0
- package/dist/adapter/listen.js +261 -0
- package/dist/adapter/listen.js.map +1 -0
- package/dist/adapter/map.d.ts +1 -1
- package/dist/adapter/map.d.ts.map +1 -1
- package/dist/adapter/map.js +12 -22
- package/dist/adapter/map.js.map +1 -1
- package/dist/adapter/polls.d.ts +2 -1
- package/dist/adapter/polls.d.ts.map +1 -1
- package/dist/adapter/polls.js +14 -3
- package/dist/adapter/polls.js.map +1 -1
- package/dist/adapter/privacy.d.ts.map +1 -1
- package/dist/adapter/privacy.js +26 -11
- package/dist/adapter/privacy.js.map +1 -1
- package/dist/adapter/sends.d.ts +14 -0
- package/dist/adapter/sends.d.ts.map +1 -0
- package/dist/adapter/sends.js +156 -0
- package/dist/adapter/sends.js.map +1 -0
- package/dist/adapter/settings.js +4 -1
- package/dist/adapter/settings.js.map +1 -1
- package/dist/app.d.ts +8 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +20 -1
- package/dist/app.js.map +1 -1
- package/dist/bot/adapter.d.ts +18 -0
- package/dist/bot/adapter.d.ts.map +1 -0
- package/dist/bot/adapter.js +74 -0
- package/dist/bot/adapter.js.map +1 -0
- package/dist/bot/generated/definitions.d.ts +3 -0
- package/dist/bot/generated/definitions.d.ts.map +1 -0
- package/dist/bot/generated/definitions.js +9254 -0
- package/dist/bot/generated/definitions.js.map +1 -0
- package/dist/bot/generated/manifest.d.ts +3 -0
- package/dist/bot/generated/manifest.d.ts.map +1 -0
- package/dist/bot/generated/manifest.js +2614 -0
- package/dist/bot/generated/manifest.js.map +1 -0
- package/dist/bot/generated/schemas.d.ts +803 -0
- package/dist/bot/generated/schemas.d.ts.map +1 -0
- package/dist/bot/generated/schemas.js +3052 -0
- package/dist/bot/generated/schemas.js.map +1 -0
- package/dist/bot/generated/types.d.ts +3439 -0
- package/dist/bot/generated/types.d.ts.map +1 -0
- package/dist/bot/generated/types.js +5 -0
- package/dist/bot/generated/types.js.map +1 -0
- package/dist/bot/graph.d.ts +53 -0
- package/dist/bot/graph.d.ts.map +1 -0
- package/dist/bot/graph.js +141 -0
- package/dist/bot/graph.js.map +1 -0
- package/dist/bot/messaging.d.ts +30 -0
- package/dist/bot/messaging.d.ts.map +1 -0
- package/dist/bot/messaging.js +124 -0
- package/dist/bot/messaging.js.map +1 -0
- package/dist/bot/mime.d.ts +3 -0
- package/dist/bot/mime.d.ts.map +1 -0
- package/dist/bot/mime.js +20 -0
- package/dist/bot/mime.js.map +1 -0
- package/dist/bot/webhook.d.ts +13 -0
- package/dist/bot/webhook.d.ts.map +1 -0
- package/dist/bot/webhook.js +148 -0
- package/dist/bot/webhook.js.map +1 -0
- package/dist/commands/bot-templates.d.ts +9 -0
- package/dist/commands/bot-templates.d.ts.map +1 -0
- package/dist/commands/bot-templates.js +141 -0
- package/dist/commands/bot-templates.js.map +1 -0
- package/dist/commands/bot.d.ts +14 -0
- package/dist/commands/bot.d.ts.map +1 -0
- package/dist/commands/bot.js +208 -0
- package/dist/commands/bot.js.map +1 -0
- package/dist/commands/session.d.ts +0 -44
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +15 -141
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +9 -8
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/update.d.ts +2 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/diagnose.d.ts +6 -41
- package/dist/diagnose.d.ts.map +1 -1
- package/dist/diagnose.js.map +1 -1
- package/dist/engine/events.d.ts +1 -1
- package/dist/engine/events.d.ts.map +1 -1
- package/dist/engine/events.js.map +1 -1
- package/dist/engine/go-engine.d.ts.map +1 -1
- package/dist/engine/go-engine.js +2 -0
- package/dist/engine/go-engine.js.map +1 -1
- package/dist/messenger.d.ts +4 -1
- package/dist/messenger.d.ts.map +1 -1
- package/dist/messenger.js +5 -3
- package/dist/messenger.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +7 -1
- package/dist/program.js.map +1 -1
- package/dist/session.d.ts +56 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +136 -0
- package/dist/session.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +16 -11
- package/skills/whatsapp-cli/SKILL.md +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BotEvent, BotWebhookIntake } from "@wirecat/cli-core/cli";
|
|
2
|
+
/** The two secrets the receiver checks Meta by, kept with `bot auth set --secret <name>`. */
|
|
3
|
+
export interface WebhookSecrets {
|
|
4
|
+
/** App settings → Basic: the key of every delivery's `X-Hub-Signature-256`. */
|
|
5
|
+
appSecret: string | undefined;
|
|
6
|
+
/** Any string the owner chose and typed in the App Dashboard too; Meta echoes it in the handshake. */
|
|
7
|
+
verifyToken: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
/** One delivery's events; `statuses[]` become receipts (delivered, read) and `other` notices (sent, failed). */
|
|
10
|
+
export declare const decodeDelivery: (body: Uint8Array) => BotEvent[];
|
|
11
|
+
/** Meta's side of `bot watch --public-url`: the subscription handshake, the signature, the payload. */
|
|
12
|
+
export declare const webhookIntake: (secrets: WebhookSecrets) => BotWebhookIntake;
|
|
13
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/bot/webhook.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAoB,gBAAgB,EAAqB,MAAM,uBAAuB,CAAA;AAE5G,6FAA6F;AAC7F,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,sGAAsG;IACtG,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;CAChC;AA0GD,gHAAgH;AAChH,eAAO,MAAM,cAAc,SAAU,UAAU,KAAG,QAAQ,EAmDzD,CAAA;AAED,uGAAuG;AACvG,eAAO,MAAM,aAAa,YAAa,cAAc,KAAG,gBAiBtD,CAAA"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { CliError } from "@wirecat/cli-base";
|
|
3
|
+
const equal = (a, b) => {
|
|
4
|
+
const left = Buffer.from(a);
|
|
5
|
+
const right = Buffer.from(b);
|
|
6
|
+
return left.length === right.length && timingSafeEqual(left, right);
|
|
7
|
+
};
|
|
8
|
+
const MEDIA = ["image", "video", "audio", "document", "sticker"];
|
|
9
|
+
const KIND = {
|
|
10
|
+
image: "photo",
|
|
11
|
+
video: "video",
|
|
12
|
+
audio: "voice",
|
|
13
|
+
document: "file",
|
|
14
|
+
sticker: "sticker",
|
|
15
|
+
};
|
|
16
|
+
const iso = (seconds) => new Date(Number(seconds ?? "0") * 1000).toISOString();
|
|
17
|
+
/**
|
|
18
|
+
* The chat a person is. Meta names some people only by a business-scoped user id (the spec does not list the
|
|
19
|
+
* field yet); such a chat is `user:<id>`, a person named by number is the digits.
|
|
20
|
+
*/
|
|
21
|
+
const chatOf = (userId, phone) => userId ? `user:${userId}` : phone;
|
|
22
|
+
const textOf = (message) => {
|
|
23
|
+
if (message.text?.body !== undefined)
|
|
24
|
+
return message.text.body;
|
|
25
|
+
if (message.button?.text !== undefined)
|
|
26
|
+
return message.button.text;
|
|
27
|
+
const reply = message.interactive?.button_reply?.title ?? message.interactive?.list_reply?.title;
|
|
28
|
+
if (reply !== undefined)
|
|
29
|
+
return reply;
|
|
30
|
+
for (const kind of MEDIA) {
|
|
31
|
+
const media = message[kind];
|
|
32
|
+
if (media?.caption !== undefined)
|
|
33
|
+
return media.caption;
|
|
34
|
+
}
|
|
35
|
+
if (message.location)
|
|
36
|
+
return [message.location.name, message.location.address].filter(Boolean).join(", ");
|
|
37
|
+
return "";
|
|
38
|
+
};
|
|
39
|
+
const messageOf = (message, contact, phoneNumberId) => {
|
|
40
|
+
const chat = chatOf(contact?.user_id ?? message.from_user_id, message.from ?? contact?.wa_id) ?? "unknown";
|
|
41
|
+
const attachments = MEDIA.flatMap((kind) => {
|
|
42
|
+
const media = message[kind];
|
|
43
|
+
if (!media?.id)
|
|
44
|
+
return [];
|
|
45
|
+
return [
|
|
46
|
+
{
|
|
47
|
+
kind: KIND[kind],
|
|
48
|
+
...(media.mime_type ? { mime: media.mime_type } : {}),
|
|
49
|
+
...(media.filename ? { name: media.filename } : {}),
|
|
50
|
+
providerRef: { mediaId: media.id, ...(phoneNumberId ? { phoneNumberId } : {}) },
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
id: message.id ?? "",
|
|
56
|
+
chatId: chat,
|
|
57
|
+
senderId: chat,
|
|
58
|
+
senderName: contact?.profile?.name ?? null,
|
|
59
|
+
timestamp: iso(message.timestamp),
|
|
60
|
+
editedAt: null,
|
|
61
|
+
text: textOf(message),
|
|
62
|
+
outgoing: false,
|
|
63
|
+
attachments,
|
|
64
|
+
replyTo: null,
|
|
65
|
+
...(message.context?.id ? { replyToId: message.context.id } : {}),
|
|
66
|
+
forwardedFrom: null,
|
|
67
|
+
reactions: null,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/** One delivery's events; `statuses[]` become receipts (delivered, read) and `other` notices (sent, failed). */
|
|
71
|
+
export const decodeDelivery = (body) => {
|
|
72
|
+
let payload;
|
|
73
|
+
try {
|
|
74
|
+
payload = JSON.parse(Buffer.from(body).toString("utf8"));
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
throw new CliError("invalid_response", "the delivery is not JSON");
|
|
78
|
+
}
|
|
79
|
+
if (payload.object !== "whatsapp_business_account")
|
|
80
|
+
throw new CliError("invalid_response", "not a WhatsApp delivery");
|
|
81
|
+
const events = [];
|
|
82
|
+
for (const entry of payload.entry ?? [])
|
|
83
|
+
for (const change of entry.changes ?? []) {
|
|
84
|
+
const value = change.value ?? {};
|
|
85
|
+
if (change.field !== "messages") {
|
|
86
|
+
events.push({ event: "other", type: change.field ?? "unknown", chatId: null });
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const phoneNumberId = value.metadata?.phone_number_id;
|
|
90
|
+
for (const message of value.messages ?? []) {
|
|
91
|
+
if (!message.id)
|
|
92
|
+
continue;
|
|
93
|
+
const contact = value.contacts?.find((one) => one.wa_id !== undefined && one.wa_id === message.from) ?? value.contacts?.[0];
|
|
94
|
+
const update = { id: message.id, kind: message.type ?? "message" };
|
|
95
|
+
if (message.type === "reaction") {
|
|
96
|
+
const chat = chatOf(contact?.user_id ?? message.from_user_id, message.from) ?? null;
|
|
97
|
+
events.push({ event: "other", type: "reaction", chatId: chat, update });
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
events.push({
|
|
101
|
+
event: "message",
|
|
102
|
+
message: { ...messageOf(message, contact, phoneNumberId), chatTitle: null },
|
|
103
|
+
update,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
for (const status of value.statuses ?? []) {
|
|
107
|
+
if (!status.id || !status.status)
|
|
108
|
+
continue;
|
|
109
|
+
const chat = chatOf(status.recipient_user_id, status.recipient_id) ?? "";
|
|
110
|
+
const update = { id: `${status.id}:${status.status}`, kind: `status:${status.status}` };
|
|
111
|
+
if (status.status === "delivered" || status.status === "read")
|
|
112
|
+
events.push({
|
|
113
|
+
event: "delivery",
|
|
114
|
+
chatId: chat,
|
|
115
|
+
chatTitle: null,
|
|
116
|
+
messageId: status.id,
|
|
117
|
+
delivery: status.status,
|
|
118
|
+
at: iso(status.timestamp),
|
|
119
|
+
update,
|
|
120
|
+
});
|
|
121
|
+
else
|
|
122
|
+
events.push({ event: "other", type: `status:${status.status}`, chatId: chat || null, update });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return events;
|
|
126
|
+
};
|
|
127
|
+
/** Meta's side of `bot watch --public-url`: the subscription handshake, the signature, the payload. */
|
|
128
|
+
export const webhookIntake = (secrets) => ({
|
|
129
|
+
webhookHandshake: (request) => {
|
|
130
|
+
const query = request.url.searchParams;
|
|
131
|
+
if (query.get("hub.mode") !== "subscribe")
|
|
132
|
+
return undefined;
|
|
133
|
+
const given = query.get("hub.verify_token") ?? "";
|
|
134
|
+
if (!secrets.verifyToken || !equal(given, secrets.verifyToken))
|
|
135
|
+
return { status: 403, body: "verify token does not match" };
|
|
136
|
+
return { status: 200, body: query.get("hub.challenge") ?? "" };
|
|
137
|
+
},
|
|
138
|
+
// Over the bytes as they came: JSON parsed and written again would not match Meta's HMAC.
|
|
139
|
+
webhookAuthentic: (request) => {
|
|
140
|
+
if (!secrets.appSecret)
|
|
141
|
+
return false;
|
|
142
|
+
const given = request.headers.get("x-hub-signature-256") ?? "";
|
|
143
|
+
const wanted = `sha256=${createHmac("sha256", secrets.appSecret).update(request.body).digest("hex")}`;
|
|
144
|
+
return equal(given, wanted);
|
|
145
|
+
},
|
|
146
|
+
webhookEvents: (request) => decodeDelivery(request.body),
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/bot/webhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* `bot templates`: the approved messages a business may send outside the 24 hours after a person last wrote. Only
|
|
4
|
+
* WhatsApp has them; MAX and Telegram bots write freely.
|
|
5
|
+
*/
|
|
6
|
+
export declare const botTemplatesCommand: () => Command;
|
|
7
|
+
/** `bot media`: a file a person sent, by the media id `bot watch` kept. */
|
|
8
|
+
export declare const botMediaCommand: () => Command;
|
|
9
|
+
//# sourceMappingURL=bot-templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-templates.d.ts","sourceRoot":"","sources":["../../src/commands/bot-templates.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA2CnC;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAO,OAmFtC,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,eAAe,QAAO,OAmClC,CAAA"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import { CliError } from "@wirecat/cli-base";
|
|
3
|
+
import { annotate } from "@wirecat/cli-base/commands";
|
|
4
|
+
import { botContext, environmentOf, FETCH, itemOf, listOf, parseApiJson, REMOTE_READ, REMOTE_WRITE, renderAnswer, } from "@wirecat/cli-core/cli";
|
|
5
|
+
import { guardedWrite, newOperationId } from "@wirecat/cli-core/sends";
|
|
6
|
+
import { Command } from "commander";
|
|
7
|
+
import { required } from "../bot/adapter.js";
|
|
8
|
+
import { GraphTransport } from "../bot/graph.js";
|
|
9
|
+
import { addressOf } from "../bot/messaging.js";
|
|
10
|
+
import { settingsOf, WHATSAPP_BOT } from "./bot.js";
|
|
11
|
+
/** The profile's Graph client, its settings and its bot context, for a command of wa's own under `bot`. */
|
|
12
|
+
const graphOf = (command, context) => {
|
|
13
|
+
const settings = settingsOf(command);
|
|
14
|
+
const stored = context.tokens.read();
|
|
15
|
+
if (!stored)
|
|
16
|
+
throw new CliError("authentication_error", `no access token for profile "${context.profile}" — run \`${context.words} auth set\``);
|
|
17
|
+
const { botFetch } = environmentOf(command);
|
|
18
|
+
return {
|
|
19
|
+
settings,
|
|
20
|
+
graph: (events) => new GraphTransport({
|
|
21
|
+
token: stored.token,
|
|
22
|
+
version: settings.graphVersion,
|
|
23
|
+
...(botFetch ? { fetch: botFetch } : {}),
|
|
24
|
+
events,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const online = (command) => {
|
|
29
|
+
const context = botContext(command, WHATSAPP_BOT);
|
|
30
|
+
if (context.settings.offline)
|
|
31
|
+
throw new CliError("validation_error", `--offline reads the local copy; \`${command.name()}\` has to ask Meta`);
|
|
32
|
+
return context;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* `bot templates`: the approved messages a business may send outside the 24 hours after a person last wrote. Only
|
|
36
|
+
* WhatsApp has them; MAX and Telegram bots write freely.
|
|
37
|
+
*/
|
|
38
|
+
export const botTemplatesCommand = () => {
|
|
39
|
+
const command = new Command("templates").description("approved messages: the only kind WhatsApp delivers 24 hours after a person wrote");
|
|
40
|
+
annotate(command.command("list"), {
|
|
41
|
+
effects: REMOTE_READ,
|
|
42
|
+
examples: ["wa cloudtest bot templates list", "wa cloudtest bot templates list --name hello_world"],
|
|
43
|
+
})
|
|
44
|
+
.description("the business account's templates, with status, language and category")
|
|
45
|
+
.option("--name <name>", "only templates with this name")
|
|
46
|
+
.action(async function () {
|
|
47
|
+
const context = online(this);
|
|
48
|
+
const { settings, graph } = graphOf(this, context);
|
|
49
|
+
const { name } = this.opts();
|
|
50
|
+
await context.run(async (events) => {
|
|
51
|
+
const answer = (await graph(events).call({
|
|
52
|
+
path: `/${required(settings.wabaId, "waba_id", context.profile)}/message_templates`,
|
|
53
|
+
method: "GET",
|
|
54
|
+
query: { fields: "name,status,language,category", limit: "100", ...(name ? { name } : {}) },
|
|
55
|
+
reads: true,
|
|
56
|
+
operation: "listTemplates",
|
|
57
|
+
}));
|
|
58
|
+
const items = (answer.data ?? []).map(({ name, status, language, category }) => ({
|
|
59
|
+
name: name ?? null,
|
|
60
|
+
status: status ?? null,
|
|
61
|
+
language: language ?? null,
|
|
62
|
+
category: category ?? null,
|
|
63
|
+
}));
|
|
64
|
+
renderAnswer(this, context, listOf("bot templates list", { items, limit: 100, has_more: Boolean(answer.paging?.next) }));
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
annotate(command.command("send"), {
|
|
68
|
+
effects: REMOTE_WRITE,
|
|
69
|
+
examples: [
|
|
70
|
+
"wa cloudtest bot templates send 70000000001 hello_world",
|
|
71
|
+
`wa cloudtest bot templates send 70000000001 order_ready es --payload '[{"type":"body","parameters":[{"type":"text","text":"42"}]}]'`,
|
|
72
|
+
],
|
|
73
|
+
})
|
|
74
|
+
.description("send an approved template; hello_world is pre-approved on the test number")
|
|
75
|
+
.argument("<chat>", "a phone number in digits, or user:<id> as `bot watch` shows it")
|
|
76
|
+
.argument("<name>", "the template's name, as `bot templates list` shows it")
|
|
77
|
+
.argument("[language]", "the template's language code", "en_US")
|
|
78
|
+
.option("--payload <json>", "the values for the template's placeholders, as Meta's components array")
|
|
79
|
+
.action(async function (chat, name, language) {
|
|
80
|
+
const context = online(this);
|
|
81
|
+
const { settings, graph } = graphOf(this, context);
|
|
82
|
+
const { payload } = this.opts();
|
|
83
|
+
const parts = payload === undefined ? undefined : parseApiJson(payload);
|
|
84
|
+
if (parts !== undefined && !Array.isArray(parts))
|
|
85
|
+
throw new CliError("validation_error", "--payload is a JSON array, as Meta's template components");
|
|
86
|
+
const ref = context.chatRef(chat);
|
|
87
|
+
const body = JSON.stringify({
|
|
88
|
+
messaging_product: "whatsapp",
|
|
89
|
+
recipient_type: "individual",
|
|
90
|
+
...addressOf(ref),
|
|
91
|
+
type: "template",
|
|
92
|
+
template: { name, language: { code: language }, ...(parts ? { components: parts } : {}) },
|
|
93
|
+
});
|
|
94
|
+
await context.run(async (events) => {
|
|
95
|
+
const answer = await guardedWrite(context.guard(), { operationId: newOperationId(), key: "bot.templates.send", kind: "message", chatId: ref }, () => graph(events).call({
|
|
96
|
+
path: `/${required(settings.phoneNumberId, "phone_number_id", context.profile)}/messages`,
|
|
97
|
+
method: "POST",
|
|
98
|
+
json: body,
|
|
99
|
+
reads: false,
|
|
100
|
+
operation: "sendMessage",
|
|
101
|
+
}));
|
|
102
|
+
const id = answer.messages?.[0]?.id ?? null;
|
|
103
|
+
renderAnswer(this, context, itemOf({ chat: ref, template: name, language, id }));
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
return command;
|
|
107
|
+
};
|
|
108
|
+
/** `bot media`: a file a person sent, by the media id `bot watch` kept. */
|
|
109
|
+
export const botMediaCommand = () => {
|
|
110
|
+
const command = new Command("media").description("files people sent to the number");
|
|
111
|
+
annotate(command.command("download"), {
|
|
112
|
+
effects: FETCH,
|
|
113
|
+
examples: ["wa cloudtest bot media download 300000000000003 --output photo.jpg"],
|
|
114
|
+
})
|
|
115
|
+
.description("save a file someone sent, by its media id; Meta's link for it lasts 5 minutes")
|
|
116
|
+
.argument("<media-id>", "the media id, from the attachment `bot watch --jsonl` printed")
|
|
117
|
+
.requiredOption("--output <file>", "where to write the file")
|
|
118
|
+
.action(async function (mediaId) {
|
|
119
|
+
const context = online(this);
|
|
120
|
+
const { graph } = graphOf(this, context);
|
|
121
|
+
const { output } = this.opts();
|
|
122
|
+
if (!/^\d+$/.test(mediaId))
|
|
123
|
+
throw new CliError("validation_error", "a media id is digits");
|
|
124
|
+
await context.run(async (events) => {
|
|
125
|
+
const client = graph(events);
|
|
126
|
+
const media = (await client.call({
|
|
127
|
+
path: `/${mediaId}`,
|
|
128
|
+
method: "GET",
|
|
129
|
+
reads: true,
|
|
130
|
+
operation: "getMedia",
|
|
131
|
+
}));
|
|
132
|
+
if (!media.url)
|
|
133
|
+
throw new CliError("invalid_response", "Meta named no address for the file");
|
|
134
|
+
const file = await client.download(media.url, "downloadMedia");
|
|
135
|
+
writeFileSync(output, file.bytes, { mode: 0o600 });
|
|
136
|
+
renderAnswer(this, context, itemOf({ id: mediaId, path: output, bytes: file.bytes.length, mime: media.mime_type ?? file.type }));
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
return command;
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=bot-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-templates.js","sourceRoot":"","sources":["../../src/commands/bot-templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type BotMcp, type BotMessenger } from "@wirecat/cli-core/cli";
|
|
2
|
+
import type { Command } from "commander";
|
|
3
|
+
import { type BotSettings, resolveSettings } from "../app.js";
|
|
4
|
+
import { type Environment } from "../messenger.js";
|
|
5
|
+
export declare const settingsOf: (command: Command) => ReturnType<typeof resolveSettings> & BotSettings;
|
|
6
|
+
/** What the shared `bot` commands need from wa: a Graph API client for the profile's business number. */
|
|
7
|
+
export declare const WHATSAPP_BOT: BotMessenger;
|
|
8
|
+
type Run = (argv: string[], environment?: Environment) => Promise<number>;
|
|
9
|
+
/** `bot mcp`. The program hands in its own `run`: importing it here would close a loop through the program. */
|
|
10
|
+
export declare const botMcp: (run: Run) => BotMcp;
|
|
11
|
+
/** `bot api`: every kept Cloud API operation, from Meta's OpenAPI file — docs/dev/bot-api-coverage.md. */
|
|
12
|
+
export declare const whatsappBotApiCommand: () => Command;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=bot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../src/commands/bot.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,YAAY,EAUlB,MAAM,uBAAuB,CAAA;AAS9B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,KAAK,WAAW,EAAE,eAAe,EAAM,MAAM,WAAW,CAAA;AAMjE,OAAO,EAAE,KAAK,WAAW,EAAS,MAAM,iBAAiB,CAAA;AAEzD,eAAO,MAAM,UAAU,YAAa,OAAO,KAEsD,UAAU,CACvG,OAAO,eAAe,CACvB,GACC,WACH,CAAA;AAqBD,yGAAyG;AACzG,eAAO,MAAM,YAAY,EAAE,YAwC1B,CAAA;AAED,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;AAEzE,+GAA+G;AAC/G,eAAO,MAAM,MAAM,QAAS,GAAG,KAAG,MAGhC,CAAA;AAiFF,0GAA0G;AAC1G,eAAO,MAAM,qBAAqB,QAAO,OAiExC,CAAA"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { CliError, isCliError } from "@wirecat/cli-base";
|
|
2
|
+
import { BotTokenStore, botContext, botCopy, checkApiBody, checkApiParameter, environmentOf, generatedApiCommand, parseApiJson, } from "@wirecat/cli-core/cli";
|
|
3
|
+
import { DEFAULT_PERMISSIONS, guardedWrite, levelFor, newOperationId, readUpload, uploadBlob, } from "@wirecat/cli-core/sends";
|
|
4
|
+
import { resolveSettings, WA } from "../app.js";
|
|
5
|
+
import { required, whatsappBotAdapter } from "../bot/adapter.js";
|
|
6
|
+
import { operations } from "../bot/generated/manifest.js";
|
|
7
|
+
import { schemas } from "../bot/generated/schemas.js";
|
|
8
|
+
import { GraphTransport } from "../bot/graph.js";
|
|
9
|
+
import { mimeOf } from "../bot/mime.js";
|
|
10
|
+
import { SKILL } from "../messenger.js";
|
|
11
|
+
export const settingsOf = (command) => {
|
|
12
|
+
const { env } = environmentOf(command);
|
|
13
|
+
return resolveSettings(command.optsWithGlobals(), { env: env ?? process.env, kind: "bot" });
|
|
14
|
+
};
|
|
15
|
+
const storeOf = (command, profile) => {
|
|
16
|
+
const { keyring, env } = environmentOf(command);
|
|
17
|
+
return new BotTokenStore({ app: WA, profile, ...(env ? { env } : {}), ...(keyring ? { keyring } : {}) });
|
|
18
|
+
};
|
|
19
|
+
/** When the person last wrote to the number, from the local copy `bot watch` keeps. */
|
|
20
|
+
const lastInbound = (botId) => async (chat) => {
|
|
21
|
+
const copy = botCopy("whatsapp-bot");
|
|
22
|
+
try {
|
|
23
|
+
const page = await copy.read((store) => store.messages.messages(copy.accountOf(botId), chat, { limit: 1, outgoing: false }));
|
|
24
|
+
const last = page.items.at(-1);
|
|
25
|
+
return last ? new Date(last.timestamp) : undefined;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/** What the shared `bot` commands need from wa: a Graph API client for the profile's business number. */
|
|
32
|
+
export const WHATSAPP_BOT = {
|
|
33
|
+
app: WA,
|
|
34
|
+
provider: "whatsapp-bot",
|
|
35
|
+
name: "WhatsApp",
|
|
36
|
+
identity: true,
|
|
37
|
+
manyWebhooks: false,
|
|
38
|
+
secrets: [
|
|
39
|
+
{
|
|
40
|
+
name: "app-secret",
|
|
41
|
+
description: "the Meta app's secret, from App settings → Basic; checks each webhook delivery",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "verify-token",
|
|
45
|
+
description: "a string you choose and type in the App Dashboard's webhook setup too; answers Meta's handshake",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
resolveSettings,
|
|
49
|
+
connect: async (command, token, { stop, events } = {}) => {
|
|
50
|
+
const environment = environmentOf(command);
|
|
51
|
+
const settings = settingsOf(command);
|
|
52
|
+
const graph = new GraphTransport({
|
|
53
|
+
token,
|
|
54
|
+
version: settings.graphVersion,
|
|
55
|
+
...(environment.botFetch ? { fetch: environment.botFetch } : {}),
|
|
56
|
+
...(stop ? { signal: stop } : {}),
|
|
57
|
+
...(events ? { events } : {}),
|
|
58
|
+
});
|
|
59
|
+
const tokens = storeOf(command, settings.profile);
|
|
60
|
+
return whatsappBotAdapter(graph, settings, settings.profile, {
|
|
61
|
+
secrets: () => ({
|
|
62
|
+
appSecret: tokens.readSecret("app-secret")?.secret,
|
|
63
|
+
verifyToken: tokens.readSecret("verify-token")?.secret,
|
|
64
|
+
}),
|
|
65
|
+
keepVerifyToken: (secret) => {
|
|
66
|
+
tokens.writeSecret("verify-token", secret);
|
|
67
|
+
},
|
|
68
|
+
...(settings.phoneNumberId ? { lastInbound: lastInbound(settings.phoneNumberId) } : {}),
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
tokenStore: (command, profile) => storeOf(command, profile),
|
|
72
|
+
};
|
|
73
|
+
/** `bot mcp`. The program hands in its own `run`: importing it here would close a loop through the program. */
|
|
74
|
+
export const botMcp = (run) => ({
|
|
75
|
+
program: async () => (argv, environment) => run(argv, environment),
|
|
76
|
+
skill: SKILL,
|
|
77
|
+
});
|
|
78
|
+
/** Path parameters a bot profile's settings fill when the flag is not given. */
|
|
79
|
+
const FROM_SETTINGS = {
|
|
80
|
+
"Phone-Number-ID": "phoneNumberId",
|
|
81
|
+
"WABA-ID": "wabaId",
|
|
82
|
+
"WhatsApp-Business-Account-ID": "wabaId",
|
|
83
|
+
};
|
|
84
|
+
const SETTING_NAME = { phoneNumberId: "phone_number_id", wabaId: "waba_id" };
|
|
85
|
+
const defaults = {
|
|
86
|
+
...DEFAULT_PERMISSIONS,
|
|
87
|
+
...Object.fromEntries(operations
|
|
88
|
+
.filter((operation) => operation.effect === "destructive")
|
|
89
|
+
.map((operation) => [`bot.api.${operation.command}`, "ask"])),
|
|
90
|
+
};
|
|
91
|
+
const keyOf = (operation) => `bot.api.${operation.command}`;
|
|
92
|
+
const pathOf = (operation, given, settings) => {
|
|
93
|
+
if (operation.binding.kind !== "http")
|
|
94
|
+
throw new Error(`${operation.id} is not an HTTP operation`);
|
|
95
|
+
return operation.binding.path.replace(/^\/\{Version\}/, "").replace(/\{([^}]+)\}/g, (_, name) => {
|
|
96
|
+
const setting = FROM_SETTINGS[name];
|
|
97
|
+
const value = given[name] ?? (setting ? required(settings[setting], SETTING_NAME[setting], settings.profile) : undefined);
|
|
98
|
+
if (value === undefined)
|
|
99
|
+
throw new CliError("validation_error", `${operation.command} needs --${name.toLowerCase()}`);
|
|
100
|
+
return encodeURIComponent(value);
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* The spec lags the live API — no `recipient`, bodies closed with `additionalProperties: false` — so a body it
|
|
105
|
+
* refuses is warned about and sent: Meta is the judge. A form or multipart body is not checked against its
|
|
106
|
+
* schema at all: its file field holds a local path here, not what the schema describes.
|
|
107
|
+
*/
|
|
108
|
+
const checkedBody = (operation, text, warn) => {
|
|
109
|
+
if (operation.request?.contentType) {
|
|
110
|
+
if (text !== undefined && text.trim() !== "")
|
|
111
|
+
parseApiJson(text);
|
|
112
|
+
return text;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
return checkApiBody(operation, text, schemas);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (!isCliError(error) || !error.message.startsWith("the body does not match"))
|
|
119
|
+
throw error;
|
|
120
|
+
warn(`${error.message} — sent anyway: Meta's file lags the live API`);
|
|
121
|
+
return text;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
/** A JSON object's fields as a form, a field holding `@<path>` as that file, read the way `messages send --file` reads one. */
|
|
125
|
+
const formOf = async (operation, text, read) => {
|
|
126
|
+
const fields = text === undefined || text.trim() === "" ? {} : parseApiJson(text);
|
|
127
|
+
if (typeof fields !== "object" || fields === null || Array.isArray(fields))
|
|
128
|
+
throw new CliError("validation_error", "a form body is a JSON object of its fields");
|
|
129
|
+
const entries = Object.entries(fields).filter(([, value]) => value !== undefined);
|
|
130
|
+
const asText = (value) => (typeof value === "string" ? value : JSON.stringify(value));
|
|
131
|
+
if (operation.request?.contentType !== "multipart/form-data") {
|
|
132
|
+
const form = new URLSearchParams();
|
|
133
|
+
for (const [name, value] of entries)
|
|
134
|
+
form.append(name, asText(value));
|
|
135
|
+
return form;
|
|
136
|
+
}
|
|
137
|
+
const form = new FormData();
|
|
138
|
+
for (const [name, value] of entries) {
|
|
139
|
+
if (typeof value === "string" && value.startsWith("@")) {
|
|
140
|
+
const file = await read(value.slice(1));
|
|
141
|
+
form.append(name, file.blob, file.name);
|
|
142
|
+
}
|
|
143
|
+
else
|
|
144
|
+
form.append(name, asText(value));
|
|
145
|
+
}
|
|
146
|
+
return form;
|
|
147
|
+
};
|
|
148
|
+
/** `bot api`: every kept Cloud API operation, from Meta's OpenAPI file — docs/dev/bot-api-coverage.md. */
|
|
149
|
+
export const whatsappBotApiCommand = () => {
|
|
150
|
+
const contextOf = (command) => botContext(command.parent ?? command, WHATSAPP_BOT);
|
|
151
|
+
const group = generatedApiCommand({
|
|
152
|
+
operations,
|
|
153
|
+
description: "every Cloud API operation wa keeps, generated from Meta's OpenAPI file",
|
|
154
|
+
checkParameter: (name, schema, raw) => checkApiParameter(name, schema, raw, schemas),
|
|
155
|
+
before: (command, operation) => {
|
|
156
|
+
const context = contextOf(command);
|
|
157
|
+
if (context.settings.offline)
|
|
158
|
+
throw new CliError("validation_error", "bot api needs Meta; --offline reads only the local copy");
|
|
159
|
+
const { level } = levelFor(context.settings.permissions, keyOf(operation), defaults);
|
|
160
|
+
if (level === "deny" || (operation.effect !== "read" && level === "readonly"))
|
|
161
|
+
throw new CliError("permission_error", "this Cloud API operation is not allowed by this profile's permissions");
|
|
162
|
+
},
|
|
163
|
+
execute: async (command, operation, input) => {
|
|
164
|
+
const context = contextOf(command);
|
|
165
|
+
const settings = settingsOf(command);
|
|
166
|
+
const anyFile = group.opts().allowAnyFile === true;
|
|
167
|
+
const text = checkedBody(operation, input.body, context.renderer.warn);
|
|
168
|
+
const path = pathOf(operation, input.path, settings);
|
|
169
|
+
const form = operation.request?.contentType
|
|
170
|
+
? await formOf(operation, text, async (file) => {
|
|
171
|
+
const upload = await readUpload("file", file, { app: WA, env: context.env, anyFile });
|
|
172
|
+
return { blob: await uploadBlob(upload.source, mimeOf(upload.name)), name: upload.name };
|
|
173
|
+
})
|
|
174
|
+
: undefined;
|
|
175
|
+
const binding = operation.binding;
|
|
176
|
+
if (binding.kind !== "http")
|
|
177
|
+
throw new Error(`${operation.id} is not an HTTP operation`);
|
|
178
|
+
const call = {
|
|
179
|
+
path,
|
|
180
|
+
method: binding.method === "DELETE" ? "DELETE" : binding.method === "GET" ? "GET" : "POST",
|
|
181
|
+
query: input.query,
|
|
182
|
+
...(form ? { form } : text !== undefined && text.trim() !== "" ? { json: text } : {}),
|
|
183
|
+
reads: operation.effect === "read",
|
|
184
|
+
operation: operation.id,
|
|
185
|
+
};
|
|
186
|
+
await context.run(async (events) => {
|
|
187
|
+
const tokens = context.tokens.read();
|
|
188
|
+
if (!tokens)
|
|
189
|
+
throw new CliError("authentication_error", `no access token for profile "${context.profile}" — run \`${context.words} auth set\``);
|
|
190
|
+
const graph = new GraphTransport({
|
|
191
|
+
token: tokens.token,
|
|
192
|
+
version: settings.graphVersion,
|
|
193
|
+
...(environmentOf(command).botFetch
|
|
194
|
+
? { fetch: environmentOf(command).botFetch }
|
|
195
|
+
: {}),
|
|
196
|
+
events,
|
|
197
|
+
});
|
|
198
|
+
const result = operation.effect === "read"
|
|
199
|
+
? await graph.call(call)
|
|
200
|
+
: await guardedWrite(context.guard(defaults), { operationId: newOperationId(), key: keyOf(operation), kind: "message", chatId: null }, () => graph.call(call));
|
|
201
|
+
context.renderer.result(result);
|
|
202
|
+
});
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
group.option("--allow-any-file", "read @path files even from credential folders or this CLI's own folders");
|
|
206
|
+
return group;
|
|
207
|
+
};
|
|
208
|
+
//# sourceMappingURL=bot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../../src/commands/bot.ts"],"names":[],"mappings":"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"}
|