@openclaw/whatsapp 2026.7.1 → 2026.7.2-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/{access-control-DYE5dXna.js → access-control-DazDX3RB.js} +4 -4
- package/dist/{account-config-6PTOSfaI.js → account-config-LiT9wWH9.js} +4 -8
- package/dist/{accounts-4YgwroRU.js → accounts-CKOFMPf-.js} +2 -3
- package/dist/{action-runtime-DPahAqxV.js → action-runtime-Bf-12TIH.js} +3 -3
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/{active-listener-B4SDebQ6.js → active-listener-5kHap439.js} +2 -2
- package/dist/{agent-tools-login-BX7eHgDm.js → agent-tools-login-DfyToBpG.js} +1 -4
- package/dist/api.js +17 -18
- package/dist/{approval-handler.runtime-DNWS4aYQ.js → approval-handler.runtime-CBiGQuZ5.js} +19 -13
- package/dist/approval-reactions-BGQoz25s.js +373 -0
- package/dist/{approval-resolver-DF-lu8k5.js → approval-resolver-DoeBBt22.js} +2 -1
- package/dist/{auth-store-Db-wfApd.js → auth-store-BQi9pZqQ.js} +31 -19
- package/dist/call-tool-api.js +6 -14
- package/dist/{channel-BWp7h1uY.js → channel-DbadDUDD.js} +84 -52
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-CKJHL_Wf.js → channel-react-action-PoRWfP9x.js} +7 -7
- package/dist/{channel.runtime-CAssfx9p.js → channel.runtime-BDDy4Lhz.js} +5 -5
- package/dist/{channel.setup-CURc5rEt.js → channel.setup-BZ-po8fg.js} +4 -5
- package/dist/config-schema-BZ8h1hWA.js +40 -0
- package/dist/{connection-controller-DkbrFSIn.js → connection-controller-C1rwfWb4.js} +52 -12
- package/dist/connection-controller-runtime-context-CbTsqmPT.js +14 -0
- package/dist/contract-api.js +2 -2
- package/dist/{directory-config-Dijefxc3.js → directory-config-CLBQrjtC.js} +3 -3
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +89 -4
- package/dist/{group-session-key-BhC1RQOE.js → group-session-key-CLTZeH_F.js} +31 -3
- package/dist/{identity-Dqft3mFA.js → identity-D7L8LCuH.js} +2 -2
- package/dist/legacy-state-migrations-api.js +1 -1
- package/dist/light-runtime-api.js +4 -4
- package/dist/{login-C48y0jlx.js → login-DGIoToX8.js} +48 -8
- package/dist/{login-qr-BjId7dll.js → login-qr-X-CZHOk9.js} +6 -7
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-DD8bXohk.js → monitor-BZ8QvCeV.js} +145 -188
- package/dist/normalize-C-Z16y7Q.js +2 -0
- package/dist/{normalize-target-bVWjgftN.js → normalize-target-DSZnHkKF.js} +14 -10
- package/dist/{resolve-outbound-target-CcdugbDf.js → resolve-outbound-target-BR97fAbB.js} +1 -1
- package/dist/runtime-api.js +10 -10
- package/dist/{send-C5CpFcBG.js → send-D9Ydnn4o.js} +25 -320
- package/dist/{send-api-DLlXl8CH.js → send-api-W33lI2nR.js} +28 -88
- package/dist/{session-errors-BAj9D2La.js → session-errors-JuazczrA.js} +2 -1
- package/dist/{session-DriaHt7V.js → session-mxWFn0eS.js} +181 -19
- package/dist/session.runtime-Nsqaehbd.js +16 -0
- package/dist/{setup-core-DH-DFPLY.js → setup-core-3aSOoK2T.js} +18 -33
- package/dist/{setup-finalize-c8dl34sO.js → setup-finalize-DBf1jjBj.js} +41 -11
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-DlWb0Z09.js → setup-surface-CiKGdNJv.js} +3 -3
- package/dist/{state-migrations-D_BmQUR9.js → state-migrations-CAMTrs2U.js} +1 -8
- package/dist/{targets-runtime-C-GiVn6Y.js → targets-runtime-Bsh0HR9y.js} +13 -6
- package/dist/text-runtime-BTGkMN0o.js +4 -0
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +72 -48
- package/package.json +4 -4
- package/dist/config-schema-mBX2nmn1.js +0 -47
- package/dist/connection-controller-registry-TSX_udJp.js +0 -22
- package/dist/constants.js +0 -2
- package/dist/normalize-Bxwqo-bW.js +0 -2
- package/dist/session.runtime-CyooSQvj.js +0 -12
- package/dist/socket-timing-DhbVFjah.js +0 -77
- package/dist/targets.js +0 -2
- package/dist/text-runtime-DdX6-mC_.js +0 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as normalizeWhatsAppTarget, n as isWhatsAppNewsletterJid, t as isWhatsAppGroupJid } from "./normalize-target-
|
|
1
|
+
import { c as normalizeWhatsAppTarget, n as isWhatsAppNewsletterJid, t as isWhatsAppGroupJid } from "./normalize-target-DSZnHkKF.js";
|
|
2
2
|
import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { missingTargetError } from "openclaw/plugin-sdk/channel-feedback";
|
|
4
4
|
//#region extensions/whatsapp/src/resolve-outbound-target.ts
|
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-
|
|
3
|
-
import { i as sendTypingWhatsApp, n as sendPollWhatsApp, r as sendReactionWhatsApp, t as sendMessageWhatsApp } from "./send-
|
|
2
|
+
import { n as whatsAppActionRuntime, t as handleWhatsAppAction } from "./action-runtime-Bf-12TIH.js";
|
|
3
|
+
import { i as sendTypingWhatsApp, n as sendPollWhatsApp, r as sendReactionWhatsApp, t as sendMessageWhatsApp } from "./send-D9Ydnn4o.js";
|
|
4
4
|
import { r as setWhatsAppRuntime } from "./runtime-BfAdAEYT.js";
|
|
5
|
-
import { n as getStatusCode, t as formatError } from "./session-errors-BAj9D2La.js";
|
|
6
5
|
import { startWebLoginWithQr, waitForWebLogin } from "./login-qr-runtime.js";
|
|
7
|
-
import { t as createWhatsAppLoginTool } from "./agent-tools-login-
|
|
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-
|
|
6
|
+
import { t as createWhatsAppLoginTool } from "./agent-tools-login-DfyToBpG.js";
|
|
7
|
+
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-BQi9pZqQ.js";
|
|
9
8
|
import { t as DEFAULT_WEB_MEDIA_BYTES } from "./constants-HU41RHGI.js";
|
|
10
|
-
import { _ as extractLocationData, b as extractText, m as extractContactContext, v as extractMediaPlaceholder } from "./send-api-
|
|
11
|
-
import { n as newConnectionId, r as waitForWaConnection, t as createWaSocket } from "./session-
|
|
12
|
-
import { n as
|
|
13
|
-
import {
|
|
14
|
-
import { t as
|
|
9
|
+
import { _ as extractLocationData, b as extractText, m as extractContactContext, v as extractMediaPlaceholder } from "./send-api-W33lI2nR.js";
|
|
10
|
+
import { n as newConnectionId, r as waitForWaConnection, t as createWaSocket } from "./session-mxWFn0eS.js";
|
|
11
|
+
import { n as getStatusCode, t as formatError } from "./session-errors-JuazczrA.js";
|
|
12
|
+
import { n as resolveWebAccountId, t as getActiveWebListener } from "./active-listener-5kHap439.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-BZ8QvCeV.js";
|
|
14
|
+
import { t as loginWeb } from "./login-DGIoToX8.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,31 +1,27 @@
|
|
|
1
|
-
import { t as resolveMergedWhatsAppAccountConfig } from "./account-config-
|
|
1
|
+
import { t as resolveMergedWhatsAppAccountConfig } from "./account-config-LiT9wWH9.js";
|
|
2
2
|
import { r as resolveDefaultWhatsAppAccountId } from "./account-ids-CB5SOWjc.js";
|
|
3
|
-
import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-
|
|
4
|
-
import {
|
|
5
|
-
import "./
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { r as isWhatsAppSocketOperationTimeoutError } from "./socket-timing-DhbVFjah.js";
|
|
10
|
-
import { i as markdownToWhatsApp, s as toWhatsappJid } from "./targets-runtime-C-GiVn6Y.js";
|
|
11
|
-
import { a as sanitizeAssistantVisibleTextWithProfile, i as sanitizeAssistantVisibleText, o as sleep, s as stripToolCallXmlTags } from "./text-runtime-DdX6-mC_.js";
|
|
3
|
+
import { a as resolveWhatsAppAccount, s as resolveWhatsAppMediaMaxBytes } from "./accounts-CKOFMPf-.js";
|
|
4
|
+
import { n as isWhatsAppNewsletterJid } from "./normalize-target-DSZnHkKF.js";
|
|
5
|
+
import { n as getWhatsAppConnectionController } from "./connection-controller-runtime-context-CbTsqmPT.js";
|
|
6
|
+
import "./normalize-C-Z16y7Q.js";
|
|
7
|
+
import { i as markdownToWhatsApp, s as toWhatsappJid } from "./targets-runtime-Bsh0HR9y.js";
|
|
8
|
+
import { a as sanitizeAssistantVisibleTextWithProfile, i as sanitizeAssistantVisibleText, o as stripToolCallXmlTags } from "./text-runtime-BTGkMN0o.js";
|
|
12
9
|
import path from "node:path";
|
|
13
|
-
import {
|
|
14
|
-
import { sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
|
|
10
|
+
import { normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
15
11
|
import { writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
|
|
16
12
|
import { resolveReactionLevel } from "openclaw/plugin-sdk/status-helpers";
|
|
17
13
|
import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
|
|
18
14
|
import { generateSecureUuid } from "openclaw/plugin-sdk/core";
|
|
15
|
+
import { PlatformMessageNotDispatchedError } from "openclaw/plugin-sdk/error-runtime";
|
|
19
16
|
import { redactIdentifier } from "openclaw/plugin-sdk/logging-core";
|
|
20
17
|
import { convertMarkdownTables, resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
21
18
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
22
19
|
import { normalizePollInput } from "openclaw/plugin-sdk/poll-runtime";
|
|
23
20
|
import { createSubsystemLogger, getChildLogger as getChildLogger$1 } from "openclaw/plugin-sdk/runtime-env";
|
|
24
|
-
import { createApprovalReactionTargetStore, listApprovalReactionBindings, resolveApprovalReactionTarget } from "openclaw/plugin-sdk/approval-reaction-runtime";
|
|
25
|
-
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
26
|
-
import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
27
21
|
import { extensionForMime } from "openclaw/plugin-sdk/media-mime";
|
|
22
|
+
import { sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
|
|
28
23
|
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, runFfmpeg } from "openclaw/plugin-sdk/media-runtime";
|
|
24
|
+
import { resolveOutboundMediaUrls } from "openclaw/plugin-sdk/reply-payload";
|
|
29
25
|
import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
30
26
|
import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
|
|
31
27
|
//#region extensions/whatsapp/src/reaction-level.ts
|
|
@@ -41,272 +37,6 @@ function resolveWhatsAppReactionLevel(params) {
|
|
|
41
37
|
});
|
|
42
38
|
}
|
|
43
39
|
//#endregion
|
|
44
|
-
//#region extensions/whatsapp/src/approval-auth.ts
|
|
45
|
-
function normalizeWhatsAppApproverId(value) {
|
|
46
|
-
const normalized = normalizeWhatsAppTarget(String(value));
|
|
47
|
-
if (!normalized || normalized.endsWith("@g.us")) return;
|
|
48
|
-
return normalized;
|
|
49
|
-
}
|
|
50
|
-
function normalizeWhatsAppApproverEntry(value) {
|
|
51
|
-
return String(value).trim() === "*" ? "*" : normalizeWhatsAppApproverId(value);
|
|
52
|
-
}
|
|
53
|
-
function getWhatsAppApprovalApprovers(params) {
|
|
54
|
-
return resolveApprovalApprovers({
|
|
55
|
-
allowFrom: resolveWhatsAppAccount({
|
|
56
|
-
cfg: params.cfg,
|
|
57
|
-
accountId: params.accountId
|
|
58
|
-
}).allowFrom,
|
|
59
|
-
normalizeApprover: normalizeWhatsAppApproverEntry
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
const whatsappResolvedApproverAuth = createResolvedApproverActionAuthAdapter({
|
|
63
|
-
channelLabel: "WhatsApp",
|
|
64
|
-
resolveApprovers: ({ cfg, accountId }) => getWhatsAppApprovalApprovers({
|
|
65
|
-
cfg,
|
|
66
|
-
accountId
|
|
67
|
-
}),
|
|
68
|
-
normalizeSenderId: (value) => normalizeWhatsAppApproverId(value)
|
|
69
|
-
});
|
|
70
|
-
const whatsappApprovalAuth = { authorizeActorAction({ cfg, accountId, senderId, approvalKind }) {
|
|
71
|
-
if (getWhatsAppApprovalApprovers({
|
|
72
|
-
cfg,
|
|
73
|
-
accountId
|
|
74
|
-
}).includes("*")) return { authorized: true };
|
|
75
|
-
return whatsappResolvedApproverAuth.authorizeActorAction({
|
|
76
|
-
cfg,
|
|
77
|
-
accountId,
|
|
78
|
-
senderId,
|
|
79
|
-
action: "approve",
|
|
80
|
-
approvalKind
|
|
81
|
-
});
|
|
82
|
-
} };
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region extensions/whatsapp/src/approval-reactions.ts
|
|
85
|
-
const PERSISTENT_NAMESPACE = "whatsapp.approval-reactions";
|
|
86
|
-
const PERSISTENT_MAX_ENTRIES = 1e3;
|
|
87
|
-
const DEFAULT_REACTION_TARGET_TTL_MS = 1440 * 60 * 1e3;
|
|
88
|
-
const resolverRuntimeLoader = createLazyRuntimeModule(() => import("./approval-resolver-DF-lu8k5.js"));
|
|
89
|
-
const whatsappApprovalReactionTargets = createApprovalReactionTargetStore({
|
|
90
|
-
namespace: PERSISTENT_NAMESPACE,
|
|
91
|
-
maxEntries: PERSISTENT_MAX_ENTRIES,
|
|
92
|
-
defaultTtlMs: DEFAULT_REACTION_TARGET_TTL_MS,
|
|
93
|
-
openStore: (storeParams) => getOptionalWhatsAppRuntime()?.state.openKeyedStore(storeParams),
|
|
94
|
-
logPersistentError: reportPersistentApprovalReactionError,
|
|
95
|
-
readPersistedTarget
|
|
96
|
-
});
|
|
97
|
-
const loadApprovalResolver = resolverRuntimeLoader;
|
|
98
|
-
function buildReactionTargetKey(params) {
|
|
99
|
-
const accountId = params.accountId.trim();
|
|
100
|
-
const remoteJid = params.remoteJid.trim();
|
|
101
|
-
const messageId = params.messageId.trim();
|
|
102
|
-
if (!accountId || !remoteJid || !messageId) return null;
|
|
103
|
-
return `${accountId}:${remoteJid}:${messageId}`;
|
|
104
|
-
}
|
|
105
|
-
function addCandidateRemoteJid(target, value) {
|
|
106
|
-
const remoteJid = value?.trim();
|
|
107
|
-
if (remoteJid && !target.includes(remoteJid)) target.push(remoteJid);
|
|
108
|
-
}
|
|
109
|
-
function reportPersistentApprovalReactionError(error) {
|
|
110
|
-
try {
|
|
111
|
-
getOptionalWhatsAppRuntime()?.logging.getChildLogger({
|
|
112
|
-
plugin: "whatsapp",
|
|
113
|
-
feature: "approval-reaction-state"
|
|
114
|
-
}).warn("WhatsApp persistent approval reaction state failed", { error: String(error) });
|
|
115
|
-
} catch {}
|
|
116
|
-
}
|
|
117
|
-
function readPersistedTarget(target) {
|
|
118
|
-
const value = target;
|
|
119
|
-
if (!value || typeof value.approvalId !== "string" || !Array.isArray(value.allowedDecisions)) return null;
|
|
120
|
-
return {
|
|
121
|
-
approvalId: value.approvalId,
|
|
122
|
-
...value.approvalKind === "exec" || value.approvalKind === "plugin" ? { approvalKind: value.approvalKind } : {},
|
|
123
|
-
allowedDecisions: value.allowedDecisions
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
function listWhatsAppApprovalReactionBindings(allowedDecisions) {
|
|
127
|
-
return listApprovalReactionBindings({ allowedDecisions });
|
|
128
|
-
}
|
|
129
|
-
function normalizeApprovalDecision(value) {
|
|
130
|
-
const normalized = value.trim().toLowerCase();
|
|
131
|
-
if (normalized === "always") return "allow-always";
|
|
132
|
-
if (normalized === "allow-once" || normalized === "allow-always" || normalized === "deny") return normalized;
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
const APPROVAL_ID_LINE_RE = /^\s*ID:\s*([A-Za-z0-9][A-Za-z0-9._:-]*)\s*$/i;
|
|
136
|
-
const APPROVE_COMMAND_LINE_RE = /\/approve(?:@[^\s]+)?\s+([A-Za-z0-9][A-Za-z0-9._:-]*)\s+(.+)$/i;
|
|
137
|
-
function extractWhatsAppApprovalPromptBinding(text) {
|
|
138
|
-
const lines = text.split(/\r?\n/);
|
|
139
|
-
const idHeaderMatch = lines.map((line) => line.match(APPROVAL_ID_LINE_RE)).find((match) => Boolean(match));
|
|
140
|
-
if (!idHeaderMatch) return null;
|
|
141
|
-
const approvalId = idHeaderMatch[1];
|
|
142
|
-
const allowedDecisions = [];
|
|
143
|
-
for (const line of lines) {
|
|
144
|
-
const match = line.match(APPROVE_COMMAND_LINE_RE);
|
|
145
|
-
if (!match || match[1] !== approvalId) continue;
|
|
146
|
-
for (const decisionText of match[2].split(/[\s|,]+/)) {
|
|
147
|
-
const decision = normalizeApprovalDecision(decisionText);
|
|
148
|
-
if (decision && !allowedDecisions.includes(decision)) allowedDecisions.push(decision);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return allowedDecisions.length > 0 ? {
|
|
152
|
-
approvalId,
|
|
153
|
-
allowedDecisions
|
|
154
|
-
} : null;
|
|
155
|
-
}
|
|
156
|
-
function registerWhatsAppApprovalReactionTarget(params) {
|
|
157
|
-
const key = buildReactionTargetKey(params);
|
|
158
|
-
const approvalId = params.approvalId.trim();
|
|
159
|
-
const allowedDecisions = listWhatsAppApprovalReactionBindings(params.allowedDecisions).map((binding) => binding.decision);
|
|
160
|
-
if (!key || !approvalId || allowedDecisions.length === 0) return null;
|
|
161
|
-
const target = {
|
|
162
|
-
approvalId,
|
|
163
|
-
approvalKind: approvalId.startsWith("plugin:") ? "plugin" : "exec",
|
|
164
|
-
allowedDecisions
|
|
165
|
-
};
|
|
166
|
-
whatsappApprovalReactionTargets.register(key, target, { ttlMs: params.ttlMs });
|
|
167
|
-
return target;
|
|
168
|
-
}
|
|
169
|
-
function registerWhatsAppApprovalReactionTargetForOutboundMessage(params) {
|
|
170
|
-
const binding = extractWhatsAppApprovalPromptBinding(params.text);
|
|
171
|
-
if (!binding) return false;
|
|
172
|
-
return Boolean(registerWhatsAppApprovalReactionTarget({
|
|
173
|
-
accountId: params.accountId,
|
|
174
|
-
remoteJid: params.remoteJid,
|
|
175
|
-
messageId: params.messageId,
|
|
176
|
-
approvalId: binding.approvalId,
|
|
177
|
-
allowedDecisions: binding.allowedDecisions,
|
|
178
|
-
ttlMs: params.ttlMs
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
function unregisterWhatsAppApprovalReactionTarget(params) {
|
|
182
|
-
const key = buildReactionTargetKey(params);
|
|
183
|
-
if (!key) return;
|
|
184
|
-
whatsappApprovalReactionTargets.delete(key);
|
|
185
|
-
}
|
|
186
|
-
function resolveTarget(params) {
|
|
187
|
-
const resolved = resolveApprovalReactionTarget({
|
|
188
|
-
target: params.target,
|
|
189
|
-
reactionKey: params.reactionKey
|
|
190
|
-
});
|
|
191
|
-
return resolved ? {
|
|
192
|
-
approvalId: resolved.approvalId,
|
|
193
|
-
decision: resolved.decision
|
|
194
|
-
} : null;
|
|
195
|
-
}
|
|
196
|
-
async function resolveWhatsAppApprovalReactionTargetWithPersistence(params) {
|
|
197
|
-
const key = buildReactionTargetKey(params);
|
|
198
|
-
if (!key) return null;
|
|
199
|
-
return resolveTarget({
|
|
200
|
-
target: await whatsappApprovalReactionTargets.lookup(key),
|
|
201
|
-
reactionKey: params.reactionKey
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
async function resolveWhatsAppApprovalReactionTargetFromCandidates(params) {
|
|
205
|
-
const candidateRemoteJids = [];
|
|
206
|
-
for (const observedRemoteJid of params.observedRemoteJids) {
|
|
207
|
-
addCandidateRemoteJid(candidateRemoteJids, observedRemoteJid);
|
|
208
|
-
try {
|
|
209
|
-
for (const candidate of await params.resolveReactionTargetJids?.(observedRemoteJid) ?? []) addCandidateRemoteJid(candidateRemoteJids, candidate);
|
|
210
|
-
} catch (error) {
|
|
211
|
-
params.logVerboseMessage?.(`whatsapp: approval reaction target JID mapping failed for ${observedRemoteJid}: ${String(error)}`);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
for (const remoteJid of candidateRemoteJids) {
|
|
215
|
-
const target = await resolveWhatsAppApprovalReactionTargetWithPersistence({
|
|
216
|
-
accountId: params.accountId,
|
|
217
|
-
remoteJid,
|
|
218
|
-
messageId: params.messageId,
|
|
219
|
-
reactionKey: params.reactionKey
|
|
220
|
-
});
|
|
221
|
-
if (target) return {
|
|
222
|
-
...target,
|
|
223
|
-
remoteJid
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
function readWhatsAppApprovalReactionEvent(params) {
|
|
229
|
-
const msg = params.msg;
|
|
230
|
-
const reaction = msg.message?.reactionMessage;
|
|
231
|
-
const reactionKey = reaction?.text?.trim() ?? "";
|
|
232
|
-
const messageId = reaction?.key?.id?.trim() ?? "";
|
|
233
|
-
const remoteJids = [];
|
|
234
|
-
addCandidateRemoteJid(remoteJids, reaction?.key?.remoteJid);
|
|
235
|
-
addCandidateRemoteJid(remoteJids, msg.key?.remoteJid);
|
|
236
|
-
const actorJid = msg.key?.participant?.trim() || (msg.key?.fromMe ? params.selfLid?.trim() ?? params.selfJid?.trim() ?? "" : msg.key?.remoteJid?.trim() ?? "");
|
|
237
|
-
if (!reactionKey || !messageId || remoteJids.length === 0 || !actorJid) return null;
|
|
238
|
-
return {
|
|
239
|
-
remoteJids,
|
|
240
|
-
messageId,
|
|
241
|
-
actorJid,
|
|
242
|
-
reactionKey
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
async function maybeResolveWhatsAppApprovalReaction(params) {
|
|
246
|
-
const event = readWhatsAppApprovalReactionEvent({
|
|
247
|
-
msg: params.msg,
|
|
248
|
-
selfJid: params.selfJid,
|
|
249
|
-
selfLid: params.selfLid
|
|
250
|
-
});
|
|
251
|
-
if (!event) return false;
|
|
252
|
-
const target = await resolveWhatsAppApprovalReactionTargetFromCandidates({
|
|
253
|
-
accountId: params.accountId,
|
|
254
|
-
observedRemoteJids: event.remoteJids,
|
|
255
|
-
messageId: event.messageId,
|
|
256
|
-
reactionKey: event.reactionKey,
|
|
257
|
-
resolveReactionTargetJids: params.resolveReactionTargetJids,
|
|
258
|
-
logVerboseMessage: params.logVerboseMessage
|
|
259
|
-
});
|
|
260
|
-
if (!target) return false;
|
|
261
|
-
const actorId = await params.resolveInboundJid(event.actorJid);
|
|
262
|
-
if (!actorId) {
|
|
263
|
-
params.logVerboseMessage?.(`whatsapp: approval reaction ignored for ${target.approvalId}; missing actor identity`);
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
|
-
const approvalKind = target.approvalId.startsWith("plugin:") ? "plugin" : "exec";
|
|
267
|
-
if (getWhatsAppApprovalApprovers({
|
|
268
|
-
cfg: params.cfg,
|
|
269
|
-
accountId: params.accountId
|
|
270
|
-
}).length === 0) {
|
|
271
|
-
params.logVerboseMessage?.(`whatsapp: approval reaction denied id=${target.approvalId}; reactions require explicit approvers`);
|
|
272
|
-
return true;
|
|
273
|
-
}
|
|
274
|
-
if (!whatsappApprovalAuth.authorizeActorAction({
|
|
275
|
-
cfg: params.cfg,
|
|
276
|
-
accountId: params.accountId,
|
|
277
|
-
senderId: actorId,
|
|
278
|
-
action: "approve",
|
|
279
|
-
approvalKind
|
|
280
|
-
}).authorized) {
|
|
281
|
-
params.logVerboseMessage?.(`whatsapp: approval reaction denied id=${target.approvalId} sender=${actorId}`);
|
|
282
|
-
return true;
|
|
283
|
-
}
|
|
284
|
-
const { isApprovalNotFoundError, resolveWhatsAppApproval } = await loadApprovalResolver();
|
|
285
|
-
try {
|
|
286
|
-
await resolveWhatsAppApproval({
|
|
287
|
-
cfg: params.cfg,
|
|
288
|
-
approvalId: target.approvalId,
|
|
289
|
-
decision: target.decision,
|
|
290
|
-
senderId: actorId,
|
|
291
|
-
gatewayUrl: params.gatewayUrl
|
|
292
|
-
});
|
|
293
|
-
params.logVerboseMessage?.(`whatsapp: approval reaction resolved id=${target.approvalId} sender=${actorId} decision=${target.decision}`);
|
|
294
|
-
return true;
|
|
295
|
-
} catch (error) {
|
|
296
|
-
if (isApprovalNotFoundError(error)) {
|
|
297
|
-
unregisterWhatsAppApprovalReactionTarget({
|
|
298
|
-
accountId: params.accountId,
|
|
299
|
-
remoteJid: target.remoteJid,
|
|
300
|
-
messageId: event.messageId
|
|
301
|
-
});
|
|
302
|
-
params.logVerboseMessage?.(`whatsapp: approval reaction ignored for expired approval id=${target.approvalId} sender=${actorId}`);
|
|
303
|
-
return true;
|
|
304
|
-
}
|
|
305
|
-
params.logVerboseMessage?.(`whatsapp: approval reaction failed id=${target.approvalId} sender=${actorId}: ${String(error)}`);
|
|
306
|
-
return true;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
//#endregion
|
|
310
40
|
//#region extensions/whatsapp/src/document-filename.ts
|
|
311
41
|
const WHATSAPP_DEFAULT_DOCUMENT_FILE_NAME = "file";
|
|
312
42
|
function resolveWhatsAppDefaultDocumentFileName(mimetype) {
|
|
@@ -347,11 +77,15 @@ function normalizeWhatsAppPayloadTextPreservingIndentation(text) {
|
|
|
347
77
|
const normalized = stripLeadingBlankLines(finalizeWhatsAppVisibleText(sanitizeAssistantVisibleTextWithProfile(stripLeadingBlankLines(text ?? ""), "history")));
|
|
348
78
|
return normalized.trim() ? normalized : "";
|
|
349
79
|
}
|
|
350
|
-
function
|
|
351
|
-
return
|
|
80
|
+
function resolveAdditiveWhatsAppMediaUrls(payload) {
|
|
81
|
+
return normalizeUniqueStringEntries([...payload.mediaUrl ? [payload.mediaUrl] : [], ...payload.mediaUrls ?? []]);
|
|
352
82
|
}
|
|
353
83
|
function normalizeWhatsAppOutboundPayload(payload, options) {
|
|
354
|
-
const
|
|
84
|
+
const preferredMediaUrls = normalizeUniqueStringEntries(payload.mediaUrls);
|
|
85
|
+
const mediaUrls = normalizeUniqueStringEntries(resolveOutboundMediaUrls({
|
|
86
|
+
mediaUrl: payload.mediaUrl,
|
|
87
|
+
mediaUrls: preferredMediaUrls
|
|
88
|
+
}));
|
|
355
89
|
const normalizeText = options?.normalizeText ?? normalizeWhatsAppPayloadText;
|
|
356
90
|
return {
|
|
357
91
|
...payload,
|
|
@@ -463,32 +197,6 @@ function deriveWhatsAppDocumentFileName(mediaUrl) {
|
|
|
463
197
|
return (mediaUrl.split(/[?#]/, 1)[0] ?? "").split(/[\\/]/).pop() || void 0;
|
|
464
198
|
}
|
|
465
199
|
}
|
|
466
|
-
function isRetryableWhatsAppOutboundError(error) {
|
|
467
|
-
if (isWhatsAppSocketOperationTimeoutError(error)) return false;
|
|
468
|
-
return /closed|reset|timed\s*out|disconnect/i.test(formatError(error));
|
|
469
|
-
}
|
|
470
|
-
async function sendWhatsAppOutboundWithRetry(params) {
|
|
471
|
-
const maxAttempts = params.maxAttempts ?? 3;
|
|
472
|
-
let lastError;
|
|
473
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) try {
|
|
474
|
-
return await params.send();
|
|
475
|
-
} catch (error) {
|
|
476
|
-
lastError = error;
|
|
477
|
-
const errorText = formatError(error);
|
|
478
|
-
const isLastAttempt = attempt === maxAttempts;
|
|
479
|
-
if (!isRetryableWhatsAppOutboundError(error) || isLastAttempt) throw error;
|
|
480
|
-
const backoffMs = 500 * attempt;
|
|
481
|
-
await params.onRetry?.({
|
|
482
|
-
attempt,
|
|
483
|
-
maxAttempts,
|
|
484
|
-
backoffMs,
|
|
485
|
-
error,
|
|
486
|
-
errorText
|
|
487
|
-
});
|
|
488
|
-
await sleep(backoffMs);
|
|
489
|
-
}
|
|
490
|
-
throw lastError;
|
|
491
|
-
}
|
|
492
200
|
//#endregion
|
|
493
201
|
//#region extensions/whatsapp/src/outbound-media.runtime.ts
|
|
494
202
|
async function loadOutboundMediaFromUrl(mediaUrl, options = {}) {
|
|
@@ -544,8 +252,11 @@ function resolveOutboundWhatsAppAccountId(params) {
|
|
|
544
252
|
}
|
|
545
253
|
function requireOutboundActiveWebListener(params) {
|
|
546
254
|
const resolvedAccountId = resolveOutboundWhatsAppAccountId(params) ?? resolveDefaultWhatsAppAccountId(params.cfg);
|
|
547
|
-
const listener =
|
|
548
|
-
if (!listener)
|
|
255
|
+
const listener = getWhatsAppConnectionController(resolvedAccountId)?.getActiveListener() ?? null;
|
|
256
|
+
if (!listener) {
|
|
257
|
+
const cause = /* @__PURE__ */ new Error(`No active WhatsApp Web listener (account: ${resolvedAccountId}). Start the gateway, then link WhatsApp with: ${formatCliCommand(`openclaw channels login --channel whatsapp --account ${resolvedAccountId}`)}.`);
|
|
258
|
+
throw new PlatformMessageNotDispatchedError(cause.message, { cause });
|
|
259
|
+
}
|
|
549
260
|
return {
|
|
550
261
|
accountId: resolvedAccountId,
|
|
551
262
|
listener
|
|
@@ -561,7 +272,7 @@ function resolveActualSentRemoteJid(result, fallbackJid) {
|
|
|
561
272
|
async function sendMessageWhatsApp(to, body, options) {
|
|
562
273
|
let text = options.preserveLeadingWhitespace ? body : normalizeWhatsAppPayloadText(body);
|
|
563
274
|
const jid = toWhatsappJid(to);
|
|
564
|
-
const mediaUrls =
|
|
275
|
+
const mediaUrls = resolveAdditiveWhatsAppMediaUrls(options);
|
|
565
276
|
const mediaPayload = options.mediaPayload;
|
|
566
277
|
const primaryMediaUrl = mediaUrls[0] ?? mediaPayload?.fileName;
|
|
567
278
|
const hasMedia = Boolean(mediaPayload || primaryMediaUrl);
|
|
@@ -653,12 +364,6 @@ async function sendMessageWhatsApp(to, body, options) {
|
|
|
653
364
|
toJid: resolveActualSentRemoteJid(captionResult, jid)
|
|
654
365
|
});
|
|
655
366
|
}
|
|
656
|
-
if (messageId && messageId !== "unknown" && text) registerWhatsAppApprovalReactionTargetForOutboundMessage({
|
|
657
|
-
accountId: resolvedAccountId,
|
|
658
|
-
remoteJid: sentRemoteJid,
|
|
659
|
-
messageId,
|
|
660
|
-
text
|
|
661
|
-
});
|
|
662
367
|
const durationMs = Date.now() - startedAt;
|
|
663
368
|
outboundLog.info(`Sent message ${messageId} -> ${redactedJid}${hasMedia ? " (media)" : ""} (${durationMs}ms)`);
|
|
664
369
|
logger.info({
|
|
@@ -770,4 +475,4 @@ async function sendPollWhatsApp(to, poll, options) {
|
|
|
770
475
|
}
|
|
771
476
|
}
|
|
772
477
|
//#endregion
|
|
773
|
-
export { normalizeWhatsAppOutboundPayload as a, prepareWhatsAppOutboundMedia as c,
|
|
478
|
+
export { normalizeWhatsAppOutboundPayload as a, prepareWhatsAppOutboundMedia as c, sendTypingWhatsApp as i, resolveWhatsAppDocumentFileName as l, sendPollWhatsApp as n, normalizeWhatsAppPayloadText as o, sendReactionWhatsApp as r, normalizeWhatsAppPayloadTextPreservingIndentation as s, sendMessageWhatsApp as t, resolveWhatsAppReactionLevel as u };
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { n as isWhatsAppNewsletterJid } from "./normalize-target-
|
|
2
|
-
import {
|
|
3
|
-
import "./normalize-
|
|
4
|
-
import { c as toWhatsappJidWithLid, r as jidToE164, s as toWhatsappJid } from "./targets-runtime-
|
|
5
|
-
import "./text-runtime-
|
|
6
|
-
import { i as buildQuotedMessageOptions } from "./group-session-key-
|
|
7
|
-
import { c as resolveComparableIdentity } from "./identity-
|
|
1
|
+
import { n as isWhatsAppNewsletterJid } from "./normalize-target-DSZnHkKF.js";
|
|
2
|
+
import { l as resolveWhatsAppDocumentFileName } from "./send-D9Ydnn4o.js";
|
|
3
|
+
import "./normalize-C-Z16y7Q.js";
|
|
4
|
+
import { c as toWhatsappJidWithLid, r as jidToE164, s as toWhatsappJid } from "./targets-runtime-Bsh0HR9y.js";
|
|
5
|
+
import "./text-runtime-BTGkMN0o.js";
|
|
6
|
+
import { i as buildQuotedMessageOptions } from "./group-session-key-CLTZeH_F.js";
|
|
7
|
+
import { c as resolveComparableIdentity } from "./identity-D7L8LCuH.js";
|
|
8
8
|
import { normalizeLowercaseStringOrEmpty, normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
|
-
import { createMessageReceiptFromOutboundResults, listMessageReceiptPlatformIds } from "openclaw/plugin-sdk/channel-outbound";
|
|
10
9
|
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
10
|
+
import { createMessageReceiptFromOutboundResults, listMessageReceiptPlatformIds } from "openclaw/plugin-sdk/channel-outbound";
|
|
11
11
|
import { getImageMetadata, resizeToJpeg } from "openclaw/plugin-sdk/media-runtime";
|
|
12
12
|
import { formatLocationText } from "openclaw/plugin-sdk/channel-inbound";
|
|
13
13
|
import { DisconnectReason, downloadMediaMessage, extractMessageContent, getContentType, isJidGroup, normalizeMessageContent, normalizeMessageContent as normalizeMessageContent$1 } from "baileys";
|
|
14
|
-
import "openclaw/plugin-sdk/media-store";
|
|
15
14
|
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
|
|
16
15
|
//#region extensions/whatsapp/src/vcard.ts
|
|
17
16
|
const ALLOWED_VCARD_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -75,85 +74,20 @@ function normalizeVcardPhone(value) {
|
|
|
75
74
|
}
|
|
76
75
|
//#endregion
|
|
77
76
|
//#region extensions/whatsapp/src/inbound/extract.ts
|
|
78
|
-
const MESSAGE_WRAPPER_KEYS = [
|
|
79
|
-
"botInvokeMessage",
|
|
80
|
-
"ephemeralMessage",
|
|
81
|
-
"viewOnceMessage",
|
|
82
|
-
"viewOnceMessageV2",
|
|
83
|
-
"viewOnceMessageV2Extension",
|
|
84
|
-
"documentWithCaptionMessage",
|
|
85
|
-
"groupMentionedMessage"
|
|
86
|
-
];
|
|
87
|
-
const MESSAGE_CONTENT_KEYS = [
|
|
88
|
-
"conversation",
|
|
89
|
-
"extendedTextMessage",
|
|
90
|
-
"imageMessage",
|
|
91
|
-
"videoMessage",
|
|
92
|
-
"audioMessage",
|
|
93
|
-
"documentMessage",
|
|
94
|
-
"stickerMessage",
|
|
95
|
-
"locationMessage",
|
|
96
|
-
"liveLocationMessage",
|
|
97
|
-
"contactMessage",
|
|
98
|
-
"contactsArrayMessage",
|
|
99
|
-
"buttonsResponseMessage",
|
|
100
|
-
"listResponseMessage",
|
|
101
|
-
"templateButtonReplyMessage",
|
|
102
|
-
"interactiveResponseMessage",
|
|
103
|
-
"buttonsMessage",
|
|
104
|
-
"listMessage"
|
|
105
|
-
];
|
|
106
|
-
function fallbackNormalizeMessageContent(message) {
|
|
107
|
-
let current = message;
|
|
108
|
-
while (current && typeof current === "object") {
|
|
109
|
-
let unwrapped = false;
|
|
110
|
-
for (const key of MESSAGE_WRAPPER_KEYS) {
|
|
111
|
-
const candidate = current[key];
|
|
112
|
-
if (candidate && typeof candidate === "object" && "message" in candidate && candidate.message) {
|
|
113
|
-
current = candidate.message;
|
|
114
|
-
unwrapped = true;
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (!unwrapped) break;
|
|
119
|
-
}
|
|
120
|
-
return current;
|
|
121
|
-
}
|
|
122
|
-
function normalizeMessage(message) {
|
|
123
|
-
if (typeof normalizeMessageContent === "function") return normalizeMessageContent(message);
|
|
124
|
-
return fallbackNormalizeMessageContent(message);
|
|
125
|
-
}
|
|
126
|
-
function fallbackGetContentType(message) {
|
|
127
|
-
const normalized = fallbackNormalizeMessageContent(message);
|
|
128
|
-
if (!normalized || typeof normalized !== "object") return;
|
|
129
|
-
for (const key of MESSAGE_CONTENT_KEYS) if (normalized[key] != null) return key;
|
|
130
|
-
}
|
|
131
|
-
function getMessageContentType(message) {
|
|
132
|
-
if (typeof getContentType === "function") return getContentType(message);
|
|
133
|
-
return fallbackGetContentType(message);
|
|
134
|
-
}
|
|
135
|
-
function extractMessage(message) {
|
|
136
|
-
if (typeof extractMessageContent === "function") return extractMessageContent(message);
|
|
137
|
-
const normalized = fallbackNormalizeMessageContent(message);
|
|
138
|
-
const contentType = fallbackGetContentType(normalized);
|
|
139
|
-
if (!normalized || !contentType || contentType === "conversation") return normalized;
|
|
140
|
-
const candidate = normalized[contentType];
|
|
141
|
-
return candidate && typeof candidate === "object" ? candidate : normalized;
|
|
142
|
-
}
|
|
143
77
|
function getFutureProofInnerMessage(message) {
|
|
144
|
-
const contentType =
|
|
78
|
+
const contentType = getContentType(message);
|
|
145
79
|
const candidate = contentType ? message[contentType] : void 0;
|
|
146
80
|
if (candidate && typeof candidate === "object" && "message" in candidate && candidate.message && typeof candidate.message === "object") {
|
|
147
|
-
const inner =
|
|
81
|
+
const inner = normalizeMessageContent(candidate.message);
|
|
148
82
|
if (inner) {
|
|
149
|
-
const innerType =
|
|
83
|
+
const innerType = getContentType(inner);
|
|
150
84
|
if (innerType && innerType !== contentType) return inner;
|
|
151
85
|
}
|
|
152
86
|
}
|
|
153
87
|
}
|
|
154
88
|
function buildMessageChain(message) {
|
|
155
89
|
const chain = [];
|
|
156
|
-
let current =
|
|
90
|
+
let current = normalizeMessageContent(message);
|
|
157
91
|
while (current && chain.length < 4) {
|
|
158
92
|
chain.push(current);
|
|
159
93
|
current = getFutureProofInnerMessage(current);
|
|
@@ -164,7 +98,7 @@ function unwrapMessage(message) {
|
|
|
164
98
|
return buildMessageChain(message).at(-1);
|
|
165
99
|
}
|
|
166
100
|
function extractContextInfoFromMessage(message) {
|
|
167
|
-
const contentType =
|
|
101
|
+
const contentType = getContentType(message);
|
|
168
102
|
const candidate = contentType ? message[contentType] : void 0;
|
|
169
103
|
const contextInfo = candidate && typeof candidate === "object" && "contextInfo" in candidate ? candidate.contextInfo : void 0;
|
|
170
104
|
if (contextInfo) return contextInfo;
|
|
@@ -210,7 +144,7 @@ function extractMentionedJids(rawMessage) {
|
|
|
210
144
|
function extractText(rawMessage) {
|
|
211
145
|
const message = unwrapMessage(rawMessage);
|
|
212
146
|
if (!message) return;
|
|
213
|
-
const extracted =
|
|
147
|
+
const extracted = extractMessageContent(message);
|
|
214
148
|
const candidates = [message, extracted && extracted !== message ? extracted : void 0];
|
|
215
149
|
for (const candidate of candidates) {
|
|
216
150
|
if (!candidate) continue;
|
|
@@ -337,14 +271,14 @@ function describeReplyContext(rawMessage) {
|
|
|
337
271
|
const message = unwrapMessage(rawMessage);
|
|
338
272
|
if (!message) return null;
|
|
339
273
|
const contextInfo = extractContextInfo(message);
|
|
340
|
-
const quoted =
|
|
274
|
+
const quoted = normalizeMessageContent(contextInfo?.quotedMessage);
|
|
341
275
|
if (!quoted) return null;
|
|
342
276
|
const location = extractLocationData(quoted);
|
|
343
277
|
const locationText = location ? formatLocationText(location) : void 0;
|
|
344
278
|
let body = [extractText(quoted), locationText].filter(Boolean).join("\n").trim();
|
|
345
279
|
if (!body) body = extractMediaPlaceholder(quoted);
|
|
346
280
|
if (!body) {
|
|
347
|
-
const quotedType = quoted ?
|
|
281
|
+
const quotedType = quoted ? getContentType(quoted) : void 0;
|
|
348
282
|
logVerbose(`Quoted message missing extractable body${quotedType ? ` (type ${quotedType})` : ""}`);
|
|
349
283
|
return null;
|
|
350
284
|
}
|
|
@@ -457,8 +391,10 @@ function normalizeKnownUserJid(value) {
|
|
|
457
391
|
const trimmed = value.replace(/^whatsapp:/i, "").trim();
|
|
458
392
|
const jidMatch = trimmed.match(KNOWN_USER_JID_RE);
|
|
459
393
|
if (jidMatch) {
|
|
460
|
-
const
|
|
461
|
-
|
|
394
|
+
const user = jidMatch[1];
|
|
395
|
+
const rawDomain = jidMatch[2];
|
|
396
|
+
if (!user || !rawDomain) return null;
|
|
397
|
+
return `${user}@${rawDomain.toLowerCase() === "c.us" ? "s.whatsapp.net" : rawDomain.toLowerCase()}`;
|
|
462
398
|
}
|
|
463
399
|
const digits = trimmed.startsWith("+") ? trimmed.replace(/\D/g, "") : /^\d+$/.test(trimmed) ? trimmed : "";
|
|
464
400
|
return digits ? `${digits}@s.whatsapp.net` : null;
|
|
@@ -467,9 +403,11 @@ function extractKnownJidParts(value) {
|
|
|
467
403
|
const normalized = normalizeKnownUserJid(value);
|
|
468
404
|
if (!normalized) return null;
|
|
469
405
|
const match = normalized.match(/^(\d+)@(.+)$/);
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
406
|
+
const user = match?.[1];
|
|
407
|
+
const domain = match?.[2];
|
|
408
|
+
return user && domain ? {
|
|
409
|
+
user,
|
|
410
|
+
domain
|
|
473
411
|
} : null;
|
|
474
412
|
}
|
|
475
413
|
function extractPhoneDigits(value) {
|
|
@@ -555,7 +493,9 @@ function resolveWhatsAppOutboundMentions(params) {
|
|
|
555
493
|
const start = match.index;
|
|
556
494
|
const token = match[0];
|
|
557
495
|
if (shouldSkipMentionAt(params.text, start, start + token.length, codeRanges)) continue;
|
|
558
|
-
const
|
|
496
|
+
const rawDigits = match[1];
|
|
497
|
+
if (!rawDigits) continue;
|
|
498
|
+
const digits = rawDigits.replace(/\D/g, "");
|
|
559
499
|
const target = token.startsWith("@+") ? byPhone.get(digits) ?? byLid.get(digits) : byLid.get(digits) ?? byPhone.get(digits);
|
|
560
500
|
if (!target) continue;
|
|
561
501
|
if (!seenMentionJids.has(target.mentionJid)) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
1
2
|
//#region extensions/whatsapp/src/session-errors.ts
|
|
2
3
|
function safeStringify(value, limit = 800) {
|
|
3
4
|
try {
|
|
@@ -15,7 +16,7 @@ function safeStringify(value, limit = 800) {
|
|
|
15
16
|
return v;
|
|
16
17
|
}, 2);
|
|
17
18
|
if (!raw) return String(value);
|
|
18
|
-
return raw.length > limit ? `${raw
|
|
19
|
+
return raw.length > limit ? `${truncateUtf16Safe(raw, limit)}…` : raw;
|
|
19
20
|
} catch {
|
|
20
21
|
return String(value);
|
|
21
22
|
}
|