@openclaw/whatsapp 2026.5.22 → 2026.5.24-beta.2
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/dist/{action-runtime-D4UqEXqf.js → action-runtime-DGx8vCsS.js} +1 -1
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/api.js +6 -6
- package/dist/approval-handler.runtime-j8U6lgcp.js +171 -0
- package/dist/approval-resolver-e1hAVRRy.js +15 -0
- package/dist/{auth-store-GTQvJznL.js → auth-store-BrKb0mwT.js} +2 -2
- package/dist/{channel-BQqQ-Gp5.js → channel-DOxZCBxE.js} +415 -34
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-CHdR3gbn.js → channel-react-action-O7asbQQ1.js} +2 -2
- package/dist/{channel.runtime-BZ_ya3mR.js → channel.runtime-B0cFknwD.js} +4 -4
- package/dist/{channel.setup-vWI0fm8Y.js → channel.setup-Bk7Hmp4a.js} +2 -2
- package/dist/{connection-controller-9TXWZRhx.js → connection-controller-ja6z4F_k.js} +2 -2
- package/dist/light-runtime-api.js +1 -1
- package/dist/{login-nJwaNuC-.js → login-BEkrpJbZ.js} +3 -3
- package/dist/{login-qr-l4UaR8Dj.js → login-qr-BVRx8j_M.js} +3 -3
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-ClhD-fQ6.js → monitor-BU1ydkuF.js} +324 -87
- package/dist/{outbound-adapter-ltiZkW9L.js → outbound-adapter-BObZXXzU.js} +1 -1
- package/dist/outbound-payload-test-api.js +1 -1
- package/dist/{runtime-CboC4QhQ.js → runtime-BfAdAEYT.js} +2 -2
- package/dist/runtime-api.js +8 -8
- package/dist/runtime-setter-api.js +1 -1
- package/dist/send-C9jEw6hx.js +625 -0
- package/dist/{send-api-CXPUXbUL.js → send-api-CC-vHBWG.js} +2 -2
- package/dist/{session-CPsgRMMa.js → session-CDgpDc0l.js} +2 -2
- package/dist/{session.runtime-C6uBkEaI.js → session.runtime-LZFdq3yb.js} +1 -1
- package/dist/{setup-core-BTDKEc-x.js → setup-core-Ce-b_wzQ.js} +2 -2
- package/dist/{setup-finalize-DUYdQs-v.js → setup-finalize-BqOudqJw.js} +2 -2
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-Uoh9W_29.js → setup-surface-CAchPwW5.js} +2 -2
- package/dist/test-api.js +1 -1
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
- package/dist/send-E_kMiuZP.js +0 -269
package/dist/runtime-api.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { o as resolveWebCredsBackupPath, r as hasWebCredsSync, s as resolveWebCredsPath } from "./creds-files-B1kSWtBg.js";
|
|
2
|
-
import { n as whatsAppActionRuntime, t as handleWhatsAppAction } from "./action-runtime-
|
|
2
|
+
import { n as whatsAppActionRuntime, t as handleWhatsAppAction } from "./action-runtime-DGx8vCsS.js";
|
|
3
|
+
import { i as sendTypingWhatsApp, n as sendPollWhatsApp, r as sendReactionWhatsApp, t as sendMessageWhatsApp } from "./send-C9jEw6hx.js";
|
|
4
|
+
import { r as setWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
3
5
|
import { n as getStatusCode, t as formatError } from "./session-errors-BAj9D2La.js";
|
|
4
|
-
import { i as sendTypingWhatsApp, n as sendPollWhatsApp, r as sendReactionWhatsApp, t as sendMessageWhatsApp } from "./send-E_kMiuZP.js";
|
|
5
6
|
import { startWebLoginWithQr, waitForWebLogin } from "./login-qr-runtime.js";
|
|
6
7
|
import { t as createWhatsAppLoginTool } from "./agent-tools-login-BDzvb3ee.js";
|
|
7
|
-
import { n as
|
|
8
|
-
import { C as waitForCredsSaveQueue, T as writeCredsJsonAtomically, _ as readWebSelfIdentity, a as formatWhatsAppWebAuthStatusState, b as restoreCredsFromBackupIfNeeded, c as logoutWeb, d as readWebAuthExistsBestEffort, f as readWebAuthExistsForDecision, g as readWebSelfId, h as readWebAuthState, l as pickWebChannel, m as readWebAuthSnapshotBestEffort, n as WHATSAPP_AUTH_UNSTABLE_CODE, o as getWebAuthAgeMs, p as readWebAuthSnapshot, r as WhatsAppAuthUnstableError, s as logWebSelfId, t as WA_WEB_AUTH_DIR, u as readCredsJsonRaw, v as readWebSelfIdentityForDecision, w as waitForCredsSaveQueueWithTimeout, x as webAuthExists, y as resolveDefaultWebAuthDir } from "./auth-store-GTQvJznL.js";
|
|
8
|
+
import { C as waitForCredsSaveQueue, T as writeCredsJsonAtomically, _ as readWebSelfIdentity, a as formatWhatsAppWebAuthStatusState, b as restoreCredsFromBackupIfNeeded, c as logoutWeb, d as readWebAuthExistsBestEffort, f as readWebAuthExistsForDecision, g as readWebSelfId, h as readWebAuthState, l as pickWebChannel, m as readWebAuthSnapshotBestEffort, n as WHATSAPP_AUTH_UNSTABLE_CODE, o as getWebAuthAgeMs, p as readWebAuthSnapshot, r as WhatsAppAuthUnstableError, s as logWebSelfId, t as WA_WEB_AUTH_DIR, u as readCredsJsonRaw, v as readWebSelfIdentityForDecision, w as waitForCredsSaveQueueWithTimeout, x as webAuthExists, y as resolveDefaultWebAuthDir } from "./auth-store-BrKb0mwT.js";
|
|
9
9
|
import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-HU41RHGI.js";
|
|
10
|
-
import { c as extractContactContext, d as extractMediaPlaceholder, p as extractText, u as extractLocationData } from "./send-api-
|
|
11
|
-
import { n as newConnectionId, r as waitForWaConnection, t as createWaSocket } from "./session-
|
|
10
|
+
import { c as extractContactContext, d as extractMediaPlaceholder, p as extractText, u as extractLocationData } from "./send-api-CC-vHBWG.js";
|
|
11
|
+
import { n as newConnectionId, r as waitForWaConnection, t as createWaSocket } from "./session-CDgpDc0l.js";
|
|
12
12
|
import { n as resolveWebAccountId, t as getActiveWebListener } from "./active-listener-B4SDebQ6.js";
|
|
13
|
-
import { a as loadWebMediaRaw, c as monitorWebInbox, i as loadWebMedia, l as resetWebInboundDedupe, n as LocalMediaAccessError, o as optimizeImageToJpeg, r as getDefaultLocalRoots, s as optimizeImageToPng, t as monitorWebChannel } from "./monitor-
|
|
14
|
-
import { t as loginWeb } from "./login-
|
|
13
|
+
import { a as loadWebMediaRaw, c as monitorWebInbox, i as loadWebMedia, l as resetWebInboundDedupe, n as LocalMediaAccessError, o as optimizeImageToJpeg, r as getDefaultLocalRoots, s as optimizeImageToPng, t as monitorWebChannel } from "./monitor-BU1ydkuF.js";
|
|
14
|
+
import { t as loginWeb } from "./login-BEkrpJbZ.js";
|
|
15
15
|
import { HEARTBEAT_PROMPT, HEARTBEAT_TOKEN, SILENT_REPLY_TOKEN, stripHeartbeatToken } from "openclaw/plugin-sdk/reply-runtime";
|
|
16
16
|
export { DEFAULT_WEB_MEDIA_BYTES, HEARTBEAT_PROMPT, HEARTBEAT_TOKEN, LocalMediaAccessError, SILENT_REPLY_TOKEN, WA_WEB_AUTH_DIR, WHATSAPP_AUTH_UNSTABLE_CODE, WhatsAppAuthUnstableError, createWaSocket, createWhatsAppLoginTool, extractContactContext, extractLocationData, extractMediaPlaceholder, extractText, formatError, formatWhatsAppWebAuthStatusState, getActiveWebListener, getDefaultLocalRoots, getStatusCode, getWebAuthAgeMs, handleWhatsAppAction, hasWebCredsSync, loadWebMedia, loadWebMediaRaw, logWebSelfId, loginWeb, logoutWeb, monitorWebChannel, monitorWebInbox, newConnectionId, optimizeImageToJpeg, optimizeImageToPng, pickWebChannel, readCredsJsonRaw, readWebAuthExistsBestEffort, readWebAuthExistsForDecision, readWebAuthSnapshot, readWebAuthSnapshotBestEffort, readWebAuthState, readWebSelfId, readWebSelfIdentity, readWebSelfIdentityForDecision, resetWebInboundDedupe, resolveDefaultWebAuthDir, resolveWebAccountId, resolveWebCredsBackupPath, resolveWebCredsPath, restoreCredsFromBackupIfNeeded, sendMessageWhatsApp, sendPollWhatsApp, sendReactionWhatsApp, sendTypingWhatsApp, setWhatsAppRuntime, startWebLoginWithQr, stripHeartbeatToken, waitForCredsSaveQueue, waitForCredsSaveQueueWithTimeout, waitForWaConnection, waitForWebLogin, webAuthExists, whatsAppActionRuntime, writeCredsJsonAtomically };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as setWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
2
2
|
export { setWhatsAppRuntime };
|
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
+
import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.js";
|
|
3
|
+
import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-BPYgj8Fv.js";
|
|
4
|
+
import { c as normalizeWhatsAppTarget, n as isWhatsAppNewsletterJid } from "./normalize-target-bVWjgftN.js";
|
|
5
|
+
import "./normalize-Bxwqo-bW.js";
|
|
6
|
+
import { t as getOptionalWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
7
|
+
import { t as getRegisteredWhatsAppConnectionController } from "./connection-controller-registry-TSX_udJp.js";
|
|
8
|
+
import { a as resolveWhatsAppOutboundMediaUrls, i as prepareWhatsAppOutboundMedia, n as normalizeWhatsAppPayloadText, s as resolveWhatsAppDocumentFileName } from "./outbound-media-contract-ioTkt8tn.js";
|
|
9
|
+
import { d as markdownToWhatsApp, p as toWhatsappJid } from "./text-runtime-Dk37KYHj.js";
|
|
10
|
+
import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
|
|
11
|
+
import { generateSecureUuid } from "openclaw/plugin-sdk/core";
|
|
12
|
+
import { redactIdentifier } from "openclaw/plugin-sdk/logging-core";
|
|
13
|
+
import { convertMarkdownTables, resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
14
|
+
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
15
|
+
import { normalizePollInput } from "openclaw/plugin-sdk/poll-runtime";
|
|
16
|
+
import { createSubsystemLogger, getChildLogger as getChildLogger$1 } from "openclaw/plugin-sdk/runtime-env";
|
|
17
|
+
import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
18
|
+
import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
|
|
19
|
+
//#region extensions/whatsapp/src/approval-auth.ts
|
|
20
|
+
function normalizeWhatsAppApproverId(value) {
|
|
21
|
+
const normalized = normalizeWhatsAppTarget(String(value));
|
|
22
|
+
if (!normalized || normalized.endsWith("@g.us")) return;
|
|
23
|
+
return normalized;
|
|
24
|
+
}
|
|
25
|
+
function normalizeWhatsAppApproverEntry(value) {
|
|
26
|
+
return String(value).trim() === "*" ? "*" : normalizeWhatsAppApproverId(value);
|
|
27
|
+
}
|
|
28
|
+
function getWhatsAppApprovalApprovers(params) {
|
|
29
|
+
return resolveApprovalApprovers({
|
|
30
|
+
allowFrom: resolveWhatsAppAccount({
|
|
31
|
+
cfg: params.cfg,
|
|
32
|
+
accountId: params.accountId
|
|
33
|
+
}).allowFrom,
|
|
34
|
+
normalizeApprover: normalizeWhatsAppApproverEntry
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const whatsappResolvedApproverAuth = createResolvedApproverActionAuthAdapter({
|
|
38
|
+
channelLabel: "WhatsApp",
|
|
39
|
+
resolveApprovers: ({ cfg, accountId }) => getWhatsAppApprovalApprovers({
|
|
40
|
+
cfg,
|
|
41
|
+
accountId
|
|
42
|
+
}),
|
|
43
|
+
normalizeSenderId: (value) => normalizeWhatsAppApproverId(value)
|
|
44
|
+
});
|
|
45
|
+
const whatsappApprovalAuth = { authorizeActorAction({ cfg, accountId, senderId, approvalKind }) {
|
|
46
|
+
if (getWhatsAppApprovalApprovers({
|
|
47
|
+
cfg,
|
|
48
|
+
accountId
|
|
49
|
+
}).includes("*")) return { authorized: true };
|
|
50
|
+
return whatsappResolvedApproverAuth.authorizeActorAction({
|
|
51
|
+
cfg,
|
|
52
|
+
accountId,
|
|
53
|
+
senderId,
|
|
54
|
+
action: "approve",
|
|
55
|
+
approvalKind
|
|
56
|
+
});
|
|
57
|
+
} };
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region extensions/whatsapp/src/approval-reactions.ts
|
|
60
|
+
const WHATSAPP_APPROVAL_REACTION_META = {
|
|
61
|
+
"allow-once": {
|
|
62
|
+
emoji: "👍",
|
|
63
|
+
label: "Allow Once"
|
|
64
|
+
},
|
|
65
|
+
deny: {
|
|
66
|
+
emoji: "👎",
|
|
67
|
+
label: "Deny"
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const WHATSAPP_APPROVAL_REACTION_ORDER = ["allow-once", "deny"];
|
|
71
|
+
const PERSISTENT_NAMESPACE = "whatsapp.approval-reactions";
|
|
72
|
+
const PERSISTENT_MAX_ENTRIES = 1e3;
|
|
73
|
+
const DEFAULT_REACTION_TARGET_TTL_MS = 1440 * 60 * 1e3;
|
|
74
|
+
const whatsappApprovalReactionTargets = /* @__PURE__ */ new Map();
|
|
75
|
+
let persistentStore;
|
|
76
|
+
let persistentStoreDisabled = false;
|
|
77
|
+
let resolverRuntimePromise;
|
|
78
|
+
function loadApprovalResolver() {
|
|
79
|
+
resolverRuntimePromise ??= import("./approval-resolver-e1hAVRRy.js");
|
|
80
|
+
return resolverRuntimePromise;
|
|
81
|
+
}
|
|
82
|
+
function buildReactionTargetKey(params) {
|
|
83
|
+
const accountId = params.accountId.trim();
|
|
84
|
+
const remoteJid = params.remoteJid.trim();
|
|
85
|
+
const messageId = params.messageId.trim();
|
|
86
|
+
if (!accountId || !remoteJid || !messageId) return null;
|
|
87
|
+
return `${accountId}:${remoteJid}:${messageId}`;
|
|
88
|
+
}
|
|
89
|
+
function reportPersistentApprovalReactionError(error) {
|
|
90
|
+
try {
|
|
91
|
+
getOptionalWhatsAppRuntime()?.logging.getChildLogger({
|
|
92
|
+
plugin: "whatsapp",
|
|
93
|
+
feature: "approval-reaction-state"
|
|
94
|
+
}).warn("WhatsApp persistent approval reaction state failed", { error: String(error) });
|
|
95
|
+
} catch {}
|
|
96
|
+
}
|
|
97
|
+
function disablePersistentApprovalReactionStore(error) {
|
|
98
|
+
persistentStoreDisabled = true;
|
|
99
|
+
persistentStore = void 0;
|
|
100
|
+
reportPersistentApprovalReactionError(error);
|
|
101
|
+
}
|
|
102
|
+
function getPersistentApprovalReactionStore() {
|
|
103
|
+
if (persistentStoreDisabled) return;
|
|
104
|
+
if (persistentStore) return persistentStore;
|
|
105
|
+
const runtime = getOptionalWhatsAppRuntime();
|
|
106
|
+
if (!runtime) return;
|
|
107
|
+
try {
|
|
108
|
+
persistentStore = runtime.state.openKeyedStore({
|
|
109
|
+
namespace: PERSISTENT_NAMESPACE,
|
|
110
|
+
maxEntries: PERSISTENT_MAX_ENTRIES,
|
|
111
|
+
defaultTtlMs: DEFAULT_REACTION_TARGET_TTL_MS
|
|
112
|
+
});
|
|
113
|
+
return persistentStore;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
disablePersistentApprovalReactionStore(error);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function readPersistedTarget(value) {
|
|
120
|
+
const persisted = value;
|
|
121
|
+
if (persisted?.version !== 1 || !persisted.target || typeof persisted.target.approvalId !== "string" || !Array.isArray(persisted.target.allowedDecisions)) return null;
|
|
122
|
+
return persisted.target;
|
|
123
|
+
}
|
|
124
|
+
function rememberPersistentApprovalReactionTarget(params) {
|
|
125
|
+
const ttlMs = params.ttlMs == null ? DEFAULT_REACTION_TARGET_TTL_MS : Math.max(1, params.ttlMs);
|
|
126
|
+
const store = getPersistentApprovalReactionStore();
|
|
127
|
+
if (!store) return;
|
|
128
|
+
store.register(params.key, {
|
|
129
|
+
version: 1,
|
|
130
|
+
target: params.target
|
|
131
|
+
}, { ttlMs }).catch(disablePersistentApprovalReactionStore);
|
|
132
|
+
}
|
|
133
|
+
function forgetPersistentApprovalReactionTarget(key) {
|
|
134
|
+
const store = getPersistentApprovalReactionStore();
|
|
135
|
+
if (!store) return;
|
|
136
|
+
store.delete(key).catch(disablePersistentApprovalReactionStore);
|
|
137
|
+
}
|
|
138
|
+
async function lookupPersistentApprovalReactionTarget(key) {
|
|
139
|
+
const store = getPersistentApprovalReactionStore();
|
|
140
|
+
if (!store) return null;
|
|
141
|
+
try {
|
|
142
|
+
return readPersistedTarget(await store.lookup(key));
|
|
143
|
+
} catch (error) {
|
|
144
|
+
disablePersistentApprovalReactionStore(error);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function listWhatsAppApprovalReactionBindings(allowedDecisions) {
|
|
149
|
+
const allowed = new Set(allowedDecisions);
|
|
150
|
+
return WHATSAPP_APPROVAL_REACTION_ORDER.filter((decision) => allowed.has(decision)).map((decision) => ({
|
|
151
|
+
decision,
|
|
152
|
+
emoji: WHATSAPP_APPROVAL_REACTION_META[decision].emoji,
|
|
153
|
+
label: WHATSAPP_APPROVAL_REACTION_META[decision].label
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
function buildWhatsAppApprovalReactionHint(allowedDecisions) {
|
|
157
|
+
const bindings = listWhatsAppApprovalReactionBindings(allowedDecisions);
|
|
158
|
+
if (bindings.length === 0) return null;
|
|
159
|
+
return `React with:\n\n${bindings.map((binding) => `${binding.emoji} ${binding.label}`).join("\n")}`;
|
|
160
|
+
}
|
|
161
|
+
function insertWhatsAppApprovalReactionHintNearHeader(params) {
|
|
162
|
+
const lines = params.text.split(/\r?\n/);
|
|
163
|
+
const idLineIndex = lines.findIndex((line) => /^ID:\s*\S+/.test(line.trim()));
|
|
164
|
+
if (idLineIndex >= 0) {
|
|
165
|
+
const before = lines.slice(0, idLineIndex + 1).join("\n");
|
|
166
|
+
const after = lines.slice(idLineIndex + 1).join("\n").replace(/^\n+/, "");
|
|
167
|
+
return after ? `${before}\n\n${params.hint}\n\n${after}` : `${before}\n\n${params.hint}`;
|
|
168
|
+
}
|
|
169
|
+
return `${params.hint}\n\n${params.text}`;
|
|
170
|
+
}
|
|
171
|
+
function addWhatsAppApprovalReactionHintToText(params) {
|
|
172
|
+
if (/(^|\n)React with:\s*(\n|$)/i.test(params.text)) return params.text;
|
|
173
|
+
const hint = buildWhatsAppApprovalReactionHint(params.allowedDecisions);
|
|
174
|
+
return hint ? insertWhatsAppApprovalReactionHintNearHeader({
|
|
175
|
+
text: params.text,
|
|
176
|
+
hint
|
|
177
|
+
}) : params.text;
|
|
178
|
+
}
|
|
179
|
+
function appendWhatsAppApprovalReactionHintForOutboundMessage(text) {
|
|
180
|
+
if (/(^|\n)React with:\s*(\n|$)/i.test(text)) return text;
|
|
181
|
+
const binding = extractWhatsAppApprovalPromptBinding(text);
|
|
182
|
+
if (!binding) return text;
|
|
183
|
+
return addWhatsAppApprovalReactionHintToText({
|
|
184
|
+
text,
|
|
185
|
+
allowedDecisions: binding.allowedDecisions
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function resolveWhatsAppApprovalReactionDecision(reactionKey, allowedDecisions) {
|
|
189
|
+
const normalizedReaction = reactionKey.trim();
|
|
190
|
+
if (!normalizedReaction) return null;
|
|
191
|
+
const allowed = new Set(allowedDecisions);
|
|
192
|
+
for (const decision of WHATSAPP_APPROVAL_REACTION_ORDER) {
|
|
193
|
+
if (!allowed.has(decision)) continue;
|
|
194
|
+
if (WHATSAPP_APPROVAL_REACTION_META[decision].emoji === normalizedReaction) return decision;
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
function normalizeApprovalDecision(value) {
|
|
199
|
+
const normalized = value.trim().toLowerCase();
|
|
200
|
+
if (normalized === "always") return "allow-always";
|
|
201
|
+
if (normalized === "allow-once" || normalized === "allow-always" || normalized === "deny") return normalized;
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
function extractWhatsAppApprovalPromptBinding(text) {
|
|
205
|
+
const allowedDecisions = [];
|
|
206
|
+
let approvalId = "";
|
|
207
|
+
for (const line of text.split(/\r?\n/)) {
|
|
208
|
+
const match = line.match(/\/approve(?:@[^\s]+)?\s+([A-Za-z0-9][A-Za-z0-9._:-]*)\s+(.+)$/i);
|
|
209
|
+
if (!match) continue;
|
|
210
|
+
if (approvalId && match[1] !== approvalId) continue;
|
|
211
|
+
approvalId ||= match[1];
|
|
212
|
+
const decisions = match[2].split(/[\s|,]+/);
|
|
213
|
+
for (const decisionText of decisions) {
|
|
214
|
+
const decision = normalizeApprovalDecision(decisionText);
|
|
215
|
+
if (decision && !allowedDecisions.includes(decision)) allowedDecisions.push(decision);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return approvalId && allowedDecisions.length > 0 ? {
|
|
219
|
+
approvalId,
|
|
220
|
+
allowedDecisions
|
|
221
|
+
} : null;
|
|
222
|
+
}
|
|
223
|
+
function registerWhatsAppApprovalReactionTarget(params) {
|
|
224
|
+
const key = buildReactionTargetKey(params);
|
|
225
|
+
const approvalId = params.approvalId.trim();
|
|
226
|
+
const allowedDecisions = listWhatsAppApprovalReactionBindings(params.allowedDecisions).map((binding) => binding.decision);
|
|
227
|
+
if (!key || !approvalId || allowedDecisions.length === 0) return null;
|
|
228
|
+
const target = {
|
|
229
|
+
approvalId,
|
|
230
|
+
allowedDecisions
|
|
231
|
+
};
|
|
232
|
+
whatsappApprovalReactionTargets.set(key, target);
|
|
233
|
+
rememberPersistentApprovalReactionTarget({
|
|
234
|
+
key,
|
|
235
|
+
target,
|
|
236
|
+
ttlMs: params.ttlMs
|
|
237
|
+
});
|
|
238
|
+
return target;
|
|
239
|
+
}
|
|
240
|
+
function registerWhatsAppApprovalReactionTargetForOutboundMessage(params) {
|
|
241
|
+
const binding = extractWhatsAppApprovalPromptBinding(params.text);
|
|
242
|
+
if (!binding) return false;
|
|
243
|
+
return Boolean(registerWhatsAppApprovalReactionTarget({
|
|
244
|
+
accountId: params.accountId,
|
|
245
|
+
remoteJid: params.remoteJid,
|
|
246
|
+
messageId: params.messageId,
|
|
247
|
+
approvalId: binding.approvalId,
|
|
248
|
+
allowedDecisions: binding.allowedDecisions,
|
|
249
|
+
ttlMs: params.ttlMs
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
function unregisterWhatsAppApprovalReactionTarget(params) {
|
|
253
|
+
const key = buildReactionTargetKey(params);
|
|
254
|
+
if (!key) return;
|
|
255
|
+
whatsappApprovalReactionTargets.delete(key);
|
|
256
|
+
forgetPersistentApprovalReactionTarget(key);
|
|
257
|
+
}
|
|
258
|
+
function resolveTarget(params) {
|
|
259
|
+
const target = params.target;
|
|
260
|
+
if (!target) return null;
|
|
261
|
+
const decision = resolveWhatsAppApprovalReactionDecision(params.reactionKey, target.allowedDecisions);
|
|
262
|
+
return decision ? {
|
|
263
|
+
approvalId: target.approvalId,
|
|
264
|
+
decision
|
|
265
|
+
} : null;
|
|
266
|
+
}
|
|
267
|
+
async function resolveWhatsAppApprovalReactionTargetWithPersistence(params) {
|
|
268
|
+
const key = buildReactionTargetKey(params);
|
|
269
|
+
if (!key) return null;
|
|
270
|
+
const inMemory = resolveTarget({
|
|
271
|
+
target: whatsappApprovalReactionTargets.get(key),
|
|
272
|
+
reactionKey: params.reactionKey
|
|
273
|
+
});
|
|
274
|
+
if (inMemory) return inMemory;
|
|
275
|
+
return resolveTarget({
|
|
276
|
+
target: await lookupPersistentApprovalReactionTarget(key),
|
|
277
|
+
reactionKey: params.reactionKey
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
function readWhatsAppApprovalReactionEvent(params) {
|
|
281
|
+
const msg = params.msg;
|
|
282
|
+
const reaction = msg.message?.reactionMessage;
|
|
283
|
+
const reactionKey = reaction?.text?.trim() ?? "";
|
|
284
|
+
const messageId = reaction?.key?.id?.trim() ?? "";
|
|
285
|
+
const remoteJid = (reaction?.key?.remoteJid ?? msg.key?.remoteJid ?? "").trim();
|
|
286
|
+
const actorJid = msg.key?.participant?.trim() || (msg.key?.fromMe ? params.selfLid?.trim() ?? params.selfJid?.trim() ?? "" : msg.key?.remoteJid?.trim() ?? "");
|
|
287
|
+
if (!reactionKey || !messageId || !remoteJid || !actorJid) return null;
|
|
288
|
+
return {
|
|
289
|
+
remoteJid,
|
|
290
|
+
messageId,
|
|
291
|
+
actorJid,
|
|
292
|
+
reactionKey
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
async function maybeResolveWhatsAppApprovalReaction(params) {
|
|
296
|
+
const event = readWhatsAppApprovalReactionEvent({
|
|
297
|
+
msg: params.msg,
|
|
298
|
+
selfJid: params.selfJid,
|
|
299
|
+
selfLid: params.selfLid
|
|
300
|
+
});
|
|
301
|
+
if (!event) return false;
|
|
302
|
+
const target = await resolveWhatsAppApprovalReactionTargetWithPersistence({
|
|
303
|
+
accountId: params.accountId,
|
|
304
|
+
remoteJid: event.remoteJid,
|
|
305
|
+
messageId: event.messageId,
|
|
306
|
+
reactionKey: event.reactionKey
|
|
307
|
+
});
|
|
308
|
+
if (!target) return false;
|
|
309
|
+
const actorId = await params.resolveInboundJid(event.actorJid);
|
|
310
|
+
if (!actorId) {
|
|
311
|
+
params.logVerboseMessage?.(`whatsapp: approval reaction ignored for ${target.approvalId}; missing actor identity`);
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
const approvalKind = target.approvalId.startsWith("plugin:") ? "plugin" : "exec";
|
|
315
|
+
if (getWhatsAppApprovalApprovers({
|
|
316
|
+
cfg: params.cfg,
|
|
317
|
+
accountId: params.accountId
|
|
318
|
+
}).length === 0) {
|
|
319
|
+
params.logVerboseMessage?.(`whatsapp: approval reaction denied id=${target.approvalId}; reactions require explicit approvers`);
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
if (!whatsappApprovalAuth.authorizeActorAction({
|
|
323
|
+
cfg: params.cfg,
|
|
324
|
+
accountId: params.accountId,
|
|
325
|
+
senderId: actorId,
|
|
326
|
+
action: "approve",
|
|
327
|
+
approvalKind
|
|
328
|
+
}).authorized) {
|
|
329
|
+
params.logVerboseMessage?.(`whatsapp: approval reaction denied id=${target.approvalId} sender=${actorId}`);
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
const { isApprovalNotFoundError, resolveWhatsAppApproval } = await loadApprovalResolver();
|
|
333
|
+
try {
|
|
334
|
+
await resolveWhatsAppApproval({
|
|
335
|
+
cfg: params.cfg,
|
|
336
|
+
approvalId: target.approvalId,
|
|
337
|
+
decision: target.decision,
|
|
338
|
+
senderId: actorId,
|
|
339
|
+
gatewayUrl: params.gatewayUrl
|
|
340
|
+
});
|
|
341
|
+
params.logVerboseMessage?.(`whatsapp: approval reaction resolved id=${target.approvalId} sender=${actorId} decision=${target.decision}`);
|
|
342
|
+
return true;
|
|
343
|
+
} catch (error) {
|
|
344
|
+
if (isApprovalNotFoundError(error)) {
|
|
345
|
+
unregisterWhatsAppApprovalReactionTarget({
|
|
346
|
+
accountId: params.accountId,
|
|
347
|
+
remoteJid: event.remoteJid,
|
|
348
|
+
messageId: event.messageId
|
|
349
|
+
});
|
|
350
|
+
params.logVerboseMessage?.(`whatsapp: approval reaction ignored for expired approval id=${target.approvalId} sender=${actorId}`);
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
params.logVerboseMessage?.(`whatsapp: approval reaction failed id=${target.approvalId} sender=${actorId}: ${String(error)}`);
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region extensions/whatsapp/src/outbound-media.runtime.ts
|
|
359
|
+
async function loadOutboundMediaFromUrl(mediaUrl, options = {}) {
|
|
360
|
+
const readFile = options.mediaAccess?.readFile ?? options.mediaReadFile;
|
|
361
|
+
const localRoots = options.mediaAccess?.localRoots?.length && options.mediaAccess.localRoots.length > 0 ? options.mediaAccess.localRoots : options.mediaLocalRoots && options.mediaLocalRoots.length > 0 ? options.mediaLocalRoots : void 0;
|
|
362
|
+
const sharedOptions = {
|
|
363
|
+
...options.maxBytes !== void 0 ? { maxBytes: options.maxBytes } : {},
|
|
364
|
+
...options.optimizeImages !== void 0 ? { optimizeImages: options.optimizeImages } : {}
|
|
365
|
+
};
|
|
366
|
+
return await loadWebMedia(mediaUrl, readFile ? {
|
|
367
|
+
...sharedOptions,
|
|
368
|
+
localRoots: "any",
|
|
369
|
+
readFile,
|
|
370
|
+
hostReadCapability: true
|
|
371
|
+
} : {
|
|
372
|
+
...sharedOptions,
|
|
373
|
+
...localRoots ? { localRoots } : {}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region extensions/whatsapp/src/send.ts
|
|
378
|
+
var send_exports = /* @__PURE__ */ __exportAll({
|
|
379
|
+
sendMessageWhatsApp: () => sendMessageWhatsApp,
|
|
380
|
+
sendPollWhatsApp: () => sendPollWhatsApp,
|
|
381
|
+
sendReactionWhatsApp: () => sendReactionWhatsApp,
|
|
382
|
+
sendTypingWhatsApp: () => sendTypingWhatsApp
|
|
383
|
+
});
|
|
384
|
+
const outboundLog = createSubsystemLogger("gateway/channels/whatsapp").child("outbound");
|
|
385
|
+
function supportsForcedDocumentDelivery(kind) {
|
|
386
|
+
return kind === "image" || kind === "video";
|
|
387
|
+
}
|
|
388
|
+
function resolveOutboundWhatsAppAccountId(params) {
|
|
389
|
+
const explicitAccountId = params.accountId?.trim();
|
|
390
|
+
if (explicitAccountId) return explicitAccountId;
|
|
391
|
+
return resolveDefaultWhatsAppAccountId(params.cfg);
|
|
392
|
+
}
|
|
393
|
+
function requireOutboundActiveWebListener(params) {
|
|
394
|
+
const resolvedAccountId = resolveOutboundWhatsAppAccountId(params) ?? resolveDefaultWhatsAppAccountId(params.cfg);
|
|
395
|
+
const listener = getRegisteredWhatsAppConnectionController(resolvedAccountId)?.getActiveListener() ?? null;
|
|
396
|
+
if (!listener) throw new Error(`No active WhatsApp Web listener (account: ${resolvedAccountId}). Start the gateway, then link WhatsApp with: ${formatCliCommand(`openclaw channels login --channel whatsapp --account ${resolvedAccountId}`)}.`);
|
|
397
|
+
return {
|
|
398
|
+
accountId: resolvedAccountId,
|
|
399
|
+
listener
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function resolveActualSentRemoteJid(result, fallbackJid) {
|
|
403
|
+
if (!result || typeof result !== "object") return fallbackJid;
|
|
404
|
+
const rawKeys = result.keys;
|
|
405
|
+
const keys = Array.isArray(rawKeys) ? rawKeys : [];
|
|
406
|
+
for (const key of keys) if (typeof key?.remoteJid === "string" && key.remoteJid.trim()) return key.remoteJid.trim();
|
|
407
|
+
return fallbackJid;
|
|
408
|
+
}
|
|
409
|
+
async function sendMessageWhatsApp(to, body, options) {
|
|
410
|
+
let text = options.preserveLeadingWhitespace ? body : normalizeWhatsAppPayloadText(body);
|
|
411
|
+
const jid = toWhatsappJid(to);
|
|
412
|
+
const mediaUrls = resolveWhatsAppOutboundMediaUrls(options);
|
|
413
|
+
const mediaPayload = options.mediaPayload;
|
|
414
|
+
const primaryMediaUrl = mediaUrls[0] ?? mediaPayload?.fileName;
|
|
415
|
+
const hasMedia = Boolean(mediaPayload || primaryMediaUrl);
|
|
416
|
+
if (!text && !hasMedia) return {
|
|
417
|
+
messageId: "",
|
|
418
|
+
toJid: jid
|
|
419
|
+
};
|
|
420
|
+
const correlationId = generateSecureUuid();
|
|
421
|
+
const startedAt = Date.now();
|
|
422
|
+
const cfg = requireRuntimeConfig(options.cfg, "WhatsApp send");
|
|
423
|
+
const { listener: active, accountId: resolvedAccountId } = requireOutboundActiveWebListener({
|
|
424
|
+
cfg,
|
|
425
|
+
accountId: options.accountId
|
|
426
|
+
});
|
|
427
|
+
const account = resolveWhatsAppAccount({
|
|
428
|
+
cfg,
|
|
429
|
+
accountId: resolvedAccountId ?? options.accountId
|
|
430
|
+
});
|
|
431
|
+
const tableMode = resolveMarkdownTableMode({
|
|
432
|
+
cfg,
|
|
433
|
+
channel: "whatsapp",
|
|
434
|
+
accountId: resolvedAccountId ?? options.accountId
|
|
435
|
+
});
|
|
436
|
+
text = convertMarkdownTables(text ?? "", tableMode);
|
|
437
|
+
text = markdownToWhatsApp(text);
|
|
438
|
+
const redactedTo = redactIdentifier(to);
|
|
439
|
+
const logger = getChildLogger$1({
|
|
440
|
+
module: "web-outbound",
|
|
441
|
+
correlationId,
|
|
442
|
+
to: redactedTo
|
|
443
|
+
});
|
|
444
|
+
try {
|
|
445
|
+
const redactedJid = redactIdentifier(jid);
|
|
446
|
+
let mediaBuffer;
|
|
447
|
+
let mediaType;
|
|
448
|
+
let documentFileName;
|
|
449
|
+
let visibleTextAfterVoice;
|
|
450
|
+
let forceDocumentDelivery = false;
|
|
451
|
+
if (mediaPayload) {
|
|
452
|
+
const media = await prepareWhatsAppOutboundMedia(mediaPayload, primaryMediaUrl);
|
|
453
|
+
const caption = text || void 0;
|
|
454
|
+
mediaBuffer = media.buffer;
|
|
455
|
+
mediaType = media.mimetype;
|
|
456
|
+
forceDocumentDelivery = Boolean(options.forceDocument && supportsForcedDocumentDelivery(media.kind));
|
|
457
|
+
if (media.kind === "audio" && caption) {
|
|
458
|
+
visibleTextAfterVoice = caption;
|
|
459
|
+
text = "";
|
|
460
|
+
} else if (media.kind === "document") {
|
|
461
|
+
text = caption ?? "";
|
|
462
|
+
documentFileName = media.fileName;
|
|
463
|
+
} else text = caption ?? "";
|
|
464
|
+
if (forceDocumentDelivery) documentFileName ??= resolveWhatsAppDocumentFileName({
|
|
465
|
+
fileName: media.fileName,
|
|
466
|
+
mimetype: media.mimetype
|
|
467
|
+
});
|
|
468
|
+
} else if (primaryMediaUrl) {
|
|
469
|
+
const media = await prepareWhatsAppOutboundMedia(await loadOutboundMediaFromUrl(primaryMediaUrl, {
|
|
470
|
+
maxBytes: resolveWhatsAppMediaMaxBytes(account),
|
|
471
|
+
optimizeImages: options.forceDocument ? false : void 0,
|
|
472
|
+
mediaAccess: options.mediaAccess,
|
|
473
|
+
mediaLocalRoots: options.mediaLocalRoots,
|
|
474
|
+
mediaReadFile: options.mediaReadFile
|
|
475
|
+
}), primaryMediaUrl);
|
|
476
|
+
const caption = text || void 0;
|
|
477
|
+
mediaBuffer = media.buffer;
|
|
478
|
+
mediaType = media.mimetype;
|
|
479
|
+
forceDocumentDelivery = Boolean(options.forceDocument && supportsForcedDocumentDelivery(media.kind));
|
|
480
|
+
if (media.kind === "audio" && caption) {
|
|
481
|
+
visibleTextAfterVoice = caption;
|
|
482
|
+
text = "";
|
|
483
|
+
} else if (media.kind === "document") {
|
|
484
|
+
text = caption ?? "";
|
|
485
|
+
documentFileName = media.fileName;
|
|
486
|
+
} else text = caption ?? "";
|
|
487
|
+
if (forceDocumentDelivery) documentFileName ??= resolveWhatsAppDocumentFileName({
|
|
488
|
+
fileName: media.fileName,
|
|
489
|
+
mimetype: media.mimetype
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
outboundLog.info(`Sending message -> ${redactedJid}${hasMedia ? " (media)" : ""}`);
|
|
493
|
+
logger.info({
|
|
494
|
+
jid: redactedJid,
|
|
495
|
+
hasMedia
|
|
496
|
+
}, "sending message");
|
|
497
|
+
if (!isWhatsAppNewsletterJid(jid)) await active.sendComposingTo(to);
|
|
498
|
+
const accountId = Boolean(options.accountId?.trim()) ? resolvedAccountId : void 0;
|
|
499
|
+
const sendOptions = options.gifPlayback || forceDocumentDelivery || accountId || documentFileName || options.quotedMessageKey ? {
|
|
500
|
+
...options.gifPlayback ? { gifPlayback: true } : {},
|
|
501
|
+
...forceDocumentDelivery ? { asDocument: true } : {},
|
|
502
|
+
...documentFileName ? { fileName: documentFileName } : {},
|
|
503
|
+
...options.quotedMessageKey ? { quotedMessageKey: options.quotedMessageKey } : {},
|
|
504
|
+
accountId
|
|
505
|
+
} : void 0;
|
|
506
|
+
const outboundText = text ? appendWhatsAppApprovalReactionHintForOutboundMessage(text) : text;
|
|
507
|
+
const result = sendOptions ? await active.sendMessage(to, outboundText, mediaBuffer, mediaType, sendOptions) : await active.sendMessage(to, outboundText, mediaBuffer, mediaType);
|
|
508
|
+
if (visibleTextAfterVoice) if (sendOptions) await active.sendMessage(to, visibleTextAfterVoice, void 0, void 0, sendOptions);
|
|
509
|
+
else await active.sendMessage(to, visibleTextAfterVoice, void 0, void 0);
|
|
510
|
+
const messageId = result?.messageId ?? "unknown";
|
|
511
|
+
const sentRemoteJid = resolveActualSentRemoteJid(result, jid);
|
|
512
|
+
if (messageId && messageId !== "unknown" && outboundText) registerWhatsAppApprovalReactionTargetForOutboundMessage({
|
|
513
|
+
accountId: resolvedAccountId,
|
|
514
|
+
remoteJid: sentRemoteJid,
|
|
515
|
+
messageId,
|
|
516
|
+
text: outboundText
|
|
517
|
+
});
|
|
518
|
+
const durationMs = Date.now() - startedAt;
|
|
519
|
+
outboundLog.info(`Sent message ${messageId} -> ${redactedJid}${hasMedia ? " (media)" : ""} (${durationMs}ms)`);
|
|
520
|
+
logger.info({
|
|
521
|
+
jid: redactedJid,
|
|
522
|
+
messageId
|
|
523
|
+
}, "sent message");
|
|
524
|
+
return {
|
|
525
|
+
messageId,
|
|
526
|
+
toJid: sentRemoteJid
|
|
527
|
+
};
|
|
528
|
+
} catch (err) {
|
|
529
|
+
logger.error({
|
|
530
|
+
err: String(err),
|
|
531
|
+
to: redactedTo,
|
|
532
|
+
hasMedia
|
|
533
|
+
}, "failed to send via web session");
|
|
534
|
+
throw err;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
async function sendTypingWhatsApp(to, options) {
|
|
538
|
+
const { listener: active } = requireOutboundActiveWebListener({
|
|
539
|
+
cfg: requireRuntimeConfig(options.cfg, "WhatsApp typing send"),
|
|
540
|
+
accountId: options.accountId
|
|
541
|
+
});
|
|
542
|
+
if (!isWhatsAppNewsletterJid(toWhatsappJid(to))) await active.sendComposingTo(to);
|
|
543
|
+
}
|
|
544
|
+
async function sendReactionWhatsApp(chatJid, messageId, emoji, options) {
|
|
545
|
+
const correlationId = generateSecureUuid();
|
|
546
|
+
const { listener: active } = requireOutboundActiveWebListener({
|
|
547
|
+
cfg: requireRuntimeConfig(options.cfg, "WhatsApp reaction"),
|
|
548
|
+
accountId: options.accountId
|
|
549
|
+
});
|
|
550
|
+
const redactedChatJid = redactIdentifier(chatJid);
|
|
551
|
+
const logger = getChildLogger$1({
|
|
552
|
+
module: "web-outbound",
|
|
553
|
+
correlationId,
|
|
554
|
+
chatJid: redactedChatJid,
|
|
555
|
+
messageId
|
|
556
|
+
});
|
|
557
|
+
try {
|
|
558
|
+
const redactedJid = redactIdentifier(toWhatsappJid(chatJid));
|
|
559
|
+
outboundLog.info(`Sending reaction "${emoji}" -> message ${messageId}`);
|
|
560
|
+
logger.info({
|
|
561
|
+
chatJid: redactedJid,
|
|
562
|
+
messageId,
|
|
563
|
+
emoji
|
|
564
|
+
}, "sending reaction");
|
|
565
|
+
await active.sendReaction(chatJid, messageId, emoji, options.fromMe ?? false, options.participant);
|
|
566
|
+
outboundLog.info(`Sent reaction "${emoji}" -> message ${messageId}`);
|
|
567
|
+
logger.info({
|
|
568
|
+
chatJid: redactedJid,
|
|
569
|
+
messageId,
|
|
570
|
+
emoji
|
|
571
|
+
}, "sent reaction");
|
|
572
|
+
} catch (err) {
|
|
573
|
+
logger.error({
|
|
574
|
+
err: String(err),
|
|
575
|
+
chatJid: redactedChatJid,
|
|
576
|
+
messageId,
|
|
577
|
+
emoji
|
|
578
|
+
}, "failed to send reaction via web session");
|
|
579
|
+
throw err;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
async function sendPollWhatsApp(to, poll, options) {
|
|
583
|
+
const correlationId = generateSecureUuid();
|
|
584
|
+
const startedAt = Date.now();
|
|
585
|
+
const { listener: active } = requireOutboundActiveWebListener({
|
|
586
|
+
cfg: requireRuntimeConfig(options.cfg, "WhatsApp poll"),
|
|
587
|
+
accountId: options.accountId
|
|
588
|
+
});
|
|
589
|
+
const redactedTo = redactIdentifier(to);
|
|
590
|
+
const logger = getChildLogger$1({
|
|
591
|
+
module: "web-outbound",
|
|
592
|
+
correlationId,
|
|
593
|
+
to: redactedTo
|
|
594
|
+
});
|
|
595
|
+
try {
|
|
596
|
+
const jid = toWhatsappJid(to);
|
|
597
|
+
const redactedJid = redactIdentifier(jid);
|
|
598
|
+
const normalized = normalizePollInput(poll, { maxOptions: 12 });
|
|
599
|
+
outboundLog.info(`Sending poll -> ${redactedJid}`);
|
|
600
|
+
logger.info({
|
|
601
|
+
jid: redactedJid,
|
|
602
|
+
optionCount: normalized.options.length,
|
|
603
|
+
maxSelections: normalized.maxSelections
|
|
604
|
+
}, "sending poll");
|
|
605
|
+
const messageId = (await active.sendPoll(to, normalized))?.messageId ?? "unknown";
|
|
606
|
+
const durationMs = Date.now() - startedAt;
|
|
607
|
+
outboundLog.info(`Sent poll ${messageId} -> ${redactedJid} (${durationMs}ms)`);
|
|
608
|
+
logger.info({
|
|
609
|
+
jid: redactedJid,
|
|
610
|
+
messageId
|
|
611
|
+
}, "sent poll");
|
|
612
|
+
return {
|
|
613
|
+
messageId,
|
|
614
|
+
toJid: jid
|
|
615
|
+
};
|
|
616
|
+
} catch (err) {
|
|
617
|
+
logger.error({
|
|
618
|
+
err: String(err),
|
|
619
|
+
to: redactedTo
|
|
620
|
+
}, "failed to send poll via web session");
|
|
621
|
+
throw err;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
//#endregion
|
|
625
|
+
export { send_exports as a, maybeResolveWhatsAppApprovalReaction as c, getWhatsAppApprovalApprovers as d, whatsappApprovalAuth as f, sendTypingWhatsApp as i, registerWhatsAppApprovalReactionTarget as l, sendPollWhatsApp as n, addWhatsAppApprovalReactionHintToText as o, sendReactionWhatsApp as r, buildWhatsAppApprovalReactionHint as s, sendMessageWhatsApp as t, unregisterWhatsAppApprovalReactionTarget as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as isWhatsAppNewsletterJid } from "./normalize-target-bVWjgftN.js";
|
|
2
|
-
import { s as resolveWhatsAppDocumentFileName } from "./outbound-media-contract-ioTkt8tn.js";
|
|
3
2
|
import "./normalize-Bxwqo-bW.js";
|
|
3
|
+
import { s as resolveWhatsAppDocumentFileName } from "./outbound-media-contract-ioTkt8tn.js";
|
|
4
4
|
import { m as toWhatsappJidWithLid, p as toWhatsappJid, u as jidToE164 } from "./text-runtime-Dk37KYHj.js";
|
|
5
5
|
import { t as buildQuotedMessageOptions } from "./quoted-message-CveINB35.js";
|
|
6
6
|
import { c as resolveComparableIdentity } from "./identity-xoLLdqEv.js";
|
|
@@ -691,7 +691,7 @@ function createWebSendApi(params) {
|
|
|
691
691
|
return normalizeWhatsAppSendResult(result, "poll");
|
|
692
692
|
},
|
|
693
693
|
sendReaction: async (chatJid, messageId, emoji, fromMe, participant) => {
|
|
694
|
-
const jid =
|
|
694
|
+
const jid = resolveOutboundJid(chatJid);
|
|
695
695
|
return normalizeWhatsAppSendResult(await params.sock.sendMessage(jid, { react: {
|
|
696
696
|
text: emoji,
|
|
697
697
|
key: {
|