@openclaw/whatsapp 2026.5.2 → 2026.5.3-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-BQ3tCkH8.js +288 -0
- package/dist/account-config-CNQ33oav.js +47 -0
- package/dist/account-ids-DG18xddX.js +5 -0
- package/dist/accounts-BDqgpFEB.js +116 -0
- package/dist/action-runtime-DTGNgG-i.js +74 -0
- package/dist/action-runtime-api.js +2 -0
- package/dist/action-runtime.runtime.js +2 -0
- package/dist/active-listener-N7GFKsuN.js +11 -0
- package/dist/agent-tools-login-DpRxLNRB.js +89 -0
- package/dist/api.js +148 -0
- package/dist/audio-preflight.runtime-Bcdsl_ri.js +7 -0
- package/dist/auth-presence.js +32 -0
- package/dist/auth-store-BjCb50Ry.js +381 -0
- package/dist/channel-DQ-5Xoj9.js +542 -0
- package/dist/channel-config-api.js +2 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel-react-action-Df20qAy9.js +42 -0
- package/dist/channel.runtime-DKXRnA8x.js +55 -0
- package/dist/channel.setup-DOHR2BGp.js +20 -0
- package/dist/command-policy-O8sRnqUV.js +8 -0
- package/dist/config-schema-Dmo66Ubb.js +27 -0
- package/dist/connection-controller-BiHAsTM8.js +596 -0
- package/dist/connection-controller-registry-D_iIGz5m.js +22 -0
- package/dist/constants-DLGCIbfl.js +4 -0
- package/dist/constants.js +2 -0
- package/dist/contract-api.js +19 -0
- package/dist/creds-files-_2V8jzQa.js +19 -0
- package/dist/directory-config-DVs4ffXu.js +37 -0
- package/dist/directory-contract-api.js +2 -0
- package/dist/doctor-A9tXm9Om.js +48 -0
- package/dist/doctor-contract-api.js +10 -0
- package/dist/group-session-contract-B8QBn0I2.js +15 -0
- package/dist/identity-QHAlV7Fu.js +75 -0
- package/dist/index.js +18 -0
- package/dist/legacy-session-surface-api.js +8 -0
- package/dist/legacy-state-migrations-api.js +2 -0
- package/dist/light-runtime-api.js +5 -0
- package/dist/login-DymdrKca.js +52 -0
- package/dist/login-qr-DIS0Iv-7.js +378 -0
- package/dist/login-qr-api.js +2 -0
- package/dist/login-qr-runtime.js +16 -0
- package/dist/monitor-C4Fhg_lD.js +3349 -0
- package/dist/normalize-CWYiGkXw.js +2 -0
- package/dist/normalize-target-BPVHNsM5.js +74 -0
- package/dist/outbound-adapter-BssVnZdz.js +29 -0
- package/dist/outbound-base-Bq1UYEK5.js +119 -0
- package/dist/outbound-media-contract-CGss_QHy.js +163 -0
- package/dist/outbound-payload-test-api.js +2 -0
- package/dist/quoted-message-TENQzyxV.js +108 -0
- package/dist/reaction-level-CRVEVAfi.js +16 -0
- package/dist/reply-resolver.runtime-BRCgoO4C.js +2 -0
- package/dist/resolve-outbound-target-CN-Wo6IY.js +39 -0
- package/dist/rolldown-runtime-RkAeH_Qm.js +27 -0
- package/dist/runtime-6fZ67abR.js +8 -0
- package/dist/runtime-api.js +15 -0
- package/dist/runtime-group-policy-Gp1lQ0at.js +11 -0
- package/dist/secret-contract-api.js +5 -0
- package/dist/security-contract-DqH8JDX6.js +26 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/send-CIyLFxdZ.js +234 -0
- package/dist/session-contract-B0efQf9P.js +27 -0
- package/dist/session-errors-CSuKZPub.js +63 -0
- package/dist/session.runtime-C1eSE_KK.js +13 -0
- package/dist/setup-core-DZKvpzbH.js +46 -0
- package/dist/setup-entry.js +23 -0
- package/dist/setup-plugin-api.js +2 -0
- package/dist/setup-surface-ieFnIW4g.js +344 -0
- package/dist/shared-D_wzSVar.js +307 -0
- package/dist/state-migrations-DnCdvoYD.js +39 -0
- package/dist/targets.js +2 -0
- package/dist/test-api.js +3 -0
- package/dist/text-runtime-C1zNiZeO.js +116 -0
- package/package.json +14 -6
- package/action-runtime-api.ts +0 -1
- package/action-runtime.runtime.ts +0 -1
- package/api.ts +0 -213
- package/auth-presence.ts +0 -80
- package/channel-config-api.ts +0 -1
- package/channel-plugin-api.ts +0 -3
- package/config-api.ts +0 -4
- package/constants.ts +0 -1
- package/contract-api.ts +0 -29
- package/directory-contract-api.ts +0 -4
- package/doctor-contract-api.ts +0 -8
- package/index.test.ts +0 -13
- package/index.ts +0 -16
- package/legacy-session-surface-api.ts +0 -6
- package/legacy-state-migrations-api.ts +0 -1
- package/light-runtime-api.ts +0 -12
- package/login-qr-api.ts +0 -1
- package/login-qr-runtime.ts +0 -23
- package/outbound-payload-test-api.ts +0 -1
- package/runtime-api.ts +0 -84
- package/secret-contract-api.ts +0 -4
- package/security-contract-api.ts +0 -4
- package/setup-entry.test.ts +0 -21
- package/setup-entry.ts +0 -21
- package/setup-plugin-api.ts +0 -3
- package/src/account-config.ts +0 -77
- package/src/account-ids.ts +0 -13
- package/src/account-types.ts +0 -5
- package/src/accounts.test.ts +0 -182
- package/src/accounts.ts +0 -176
- package/src/accounts.whatsapp-auth.test.ts +0 -59
- package/src/action-runtime-target-auth.ts +0 -27
- package/src/action-runtime.test.ts +0 -330
- package/src/action-runtime.ts +0 -76
- package/src/active-listener.test.ts +0 -65
- package/src/active-listener.ts +0 -17
- package/src/agent-tools-login.test.ts +0 -81
- package/src/agent-tools-login.ts +0 -113
- package/src/approval-auth.test.ts +0 -24
- package/src/approval-auth.ts +0 -27
- package/src/auth-store.runtime.ts +0 -1
- package/src/auth-store.test.ts +0 -311
- package/src/auth-store.ts +0 -502
- package/src/auto-reply/config.runtime.ts +0 -16
- package/src/auto-reply/constants.ts +0 -1
- package/src/auto-reply/deliver-reply.test.ts +0 -843
- package/src/auto-reply/deliver-reply.ts +0 -279
- package/src/auto-reply/loggers.ts +0 -6
- package/src/auto-reply/mentions.ts +0 -131
- package/src/auto-reply/monitor/ack-reaction.test.ts +0 -170
- package/src/auto-reply/monitor/ack-reaction.ts +0 -99
- package/src/auto-reply/monitor/audio-preflight.runtime.ts +0 -9
- package/src/auto-reply/monitor/broadcast.ts +0 -153
- package/src/auto-reply/monitor/commands.ts +0 -19
- package/src/auto-reply/monitor/echo.ts +0 -64
- package/src/auto-reply/monitor/group-activation.runtime.ts +0 -1
- package/src/auto-reply/monitor/group-activation.test.ts +0 -189
- package/src/auto-reply/monitor/group-activation.ts +0 -73
- package/src/auto-reply/monitor/group-gating.audio-preflight.test.ts +0 -103
- package/src/auto-reply/monitor/group-gating.runtime.ts +0 -8
- package/src/auto-reply/monitor/group-gating.ts +0 -217
- package/src/auto-reply/monitor/group-members.test.ts +0 -56
- package/src/auto-reply/monitor/group-members.ts +0 -65
- package/src/auto-reply/monitor/inbound-context.test.ts +0 -97
- package/src/auto-reply/monitor/inbound-context.ts +0 -92
- package/src/auto-reply/monitor/inbound-dispatch.runtime.ts +0 -21
- package/src/auto-reply/monitor/inbound-dispatch.test.ts +0 -895
- package/src/auto-reply/monitor/inbound-dispatch.ts +0 -422
- package/src/auto-reply/monitor/last-route.test.ts +0 -37
- package/src/auto-reply/monitor/last-route.ts +0 -61
- package/src/auto-reply/monitor/message-line.runtime.ts +0 -38
- package/src/auto-reply/monitor/message-line.ts +0 -54
- package/src/auto-reply/monitor/on-message.audio-preflight.test.ts +0 -354
- package/src/auto-reply/monitor/on-message.ts +0 -291
- package/src/auto-reply/monitor/peer.ts +0 -17
- package/src/auto-reply/monitor/process-message.audio-preflight.test.ts +0 -420
- package/src/auto-reply/monitor/process-message.test.ts +0 -355
- package/src/auto-reply/monitor/process-message.ts +0 -531
- package/src/auto-reply/monitor/runtime-api.ts +0 -30
- package/src/auto-reply/monitor-state.test.ts +0 -64
- package/src/auto-reply/monitor-state.ts +0 -106
- package/src/auto-reply/monitor.ts +0 -600
- package/src/auto-reply/reply-resolver.runtime.ts +0 -1
- package/src/auto-reply/types.ts +0 -48
- package/src/auto-reply/util.ts +0 -63
- package/src/auto-reply/web-auto-reply-monitor.test.ts +0 -687
- package/src/auto-reply/web-auto-reply-utils.test.ts +0 -392
- package/src/auto-reply.broadcast-groups.combined.test.ts +0 -246
- package/src/auto-reply.broadcast-groups.test-harness.ts +0 -47
- package/src/auto-reply.impl.ts +0 -6
- package/src/auto-reply.test-harness.ts +0 -421
- package/src/auto-reply.ts +0 -1
- package/src/auto-reply.web-auto-reply.compresses-common-formats-jpeg-cap.test.ts +0 -427
- package/src/auto-reply.web-auto-reply.connection-and-logging.e2e.test.ts +0 -908
- package/src/auto-reply.web-auto-reply.last-route.test.ts +0 -184
- package/src/channel-actions.runtime.ts +0 -7
- package/src/channel-actions.test.ts +0 -216
- package/src/channel-actions.ts +0 -84
- package/src/channel-outbound.test.ts +0 -131
- package/src/channel-outbound.ts +0 -36
- package/src/channel-react-action.runtime.ts +0 -7
- package/src/channel-react-action.test.ts +0 -294
- package/src/channel-react-action.ts +0 -84
- package/src/channel.runtime.ts +0 -117
- package/src/channel.setup.test.ts +0 -461
- package/src/channel.setup.ts +0 -28
- package/src/channel.ts +0 -339
- package/src/command-policy.ts +0 -7
- package/src/config-accessors.test.ts +0 -34
- package/src/config-accessors.ts +0 -22
- package/src/config-schema.test.ts +0 -121
- package/src/config-schema.ts +0 -6
- package/src/config-ui-hints.ts +0 -24
- package/src/connection-controller-registry.test.ts +0 -27
- package/src/connection-controller-registry.ts +0 -49
- package/src/connection-controller.test.ts +0 -282
- package/src/connection-controller.ts +0 -679
- package/src/creds-files.ts +0 -19
- package/src/creds-persistence.ts +0 -102
- package/src/directory-config.test.ts +0 -60
- package/src/directory-config.ts +0 -40
- package/src/directory-contract.test.ts +0 -56
- package/src/doctor-contract.ts +0 -11
- package/src/doctor.test.ts +0 -74
- package/src/doctor.ts +0 -56
- package/src/group-intro.ts +0 -15
- package/src/group-policy.test.ts +0 -36
- package/src/group-policy.ts +0 -40
- package/src/group-session-contract.ts +0 -20
- package/src/group-session-key.test.ts +0 -53
- package/src/group-session-key.ts +0 -41
- package/src/heartbeat.ts +0 -34
- package/src/identity.ts +0 -164
- package/src/inbound/access-control.test-harness.ts +0 -37
- package/src/inbound/access-control.test.ts +0 -375
- package/src/inbound/access-control.ts +0 -237
- package/src/inbound/dedupe.ts +0 -132
- package/src/inbound/extract.test.ts +0 -282
- package/src/inbound/extract.ts +0 -488
- package/src/inbound/lifecycle.ts +0 -39
- package/src/inbound/media.node.test.ts +0 -83
- package/src/inbound/media.ts +0 -102
- package/src/inbound/monitor.ts +0 -890
- package/src/inbound/runtime-api.ts +0 -7
- package/src/inbound/save-media.runtime.ts +0 -1
- package/src/inbound/send-api.test.ts +0 -319
- package/src/inbound/send-api.ts +0 -145
- package/src/inbound/send-result.ts +0 -61
- package/src/inbound/types.ts +0 -106
- package/src/inbound-context.contract.test.ts +0 -32
- package/src/inbound-policy.ts +0 -231
- package/src/inbound.media.test.ts +0 -320
- package/src/inbound.test.ts +0 -290
- package/src/inbound.ts +0 -9
- package/src/login-qr.test.ts +0 -483
- package/src/login-qr.ts +0 -542
- package/src/login.coverage.test.ts +0 -133
- package/src/login.test.ts +0 -89
- package/src/login.ts +0 -70
- package/src/logout.test.ts +0 -162
- package/src/media.test.ts +0 -480
- package/src/media.ts +0 -10
- package/src/monitor-inbox.allows-messages-from-senders-allowfrom-list.test-support.ts +0 -400
- package/src/monitor-inbox.append-upsert.test-support.ts +0 -133
- package/src/monitor-inbox.behavior.test.ts +0 -5
- package/src/monitor-inbox.blocks-messages-from-unauthorized-senders-not-allowfrom.test-support.ts +0 -362
- package/src/monitor-inbox.captures-media-path-image-messages.test-support.ts +0 -306
- package/src/monitor-inbox.streams-inbound-messages.test-support.ts +0 -729
- package/src/monitor-inbox.test-harness.ts +0 -304
- package/src/normalize-target.ts +0 -123
- package/src/normalize.ts +0 -7
- package/src/outbound-adapter.poll.test.ts +0 -62
- package/src/outbound-adapter.sendpayload.test.ts +0 -195
- package/src/outbound-adapter.ts +0 -36
- package/src/outbound-base.test.ts +0 -560
- package/src/outbound-base.ts +0 -244
- package/src/outbound-media-contract.ts +0 -278
- package/src/outbound-media.runtime.ts +0 -36
- package/src/outbound-payload.contract.test.ts +0 -61
- package/src/outbound-send-deps.ts +0 -1
- package/src/outbound-test-support.ts +0 -16
- package/src/pairing-security.test-harness.ts +0 -59
- package/src/qr-image.ts +0 -1
- package/src/qr-terminal.ts +0 -1
- package/src/quoted-message.test.ts +0 -83
- package/src/quoted-message.ts +0 -184
- package/src/reaction-level.test.ts +0 -94
- package/src/reaction-level.ts +0 -21
- package/src/reconnect.test.ts +0 -51
- package/src/reconnect.ts +0 -55
- package/src/resolve-outbound-target.test.ts +0 -288
- package/src/resolve-outbound-target.ts +0 -58
- package/src/resolve-target.test.ts +0 -120
- package/src/runtime-api.ts +0 -59
- package/src/runtime-group-policy.ts +0 -16
- package/src/runtime.ts +0 -9
- package/src/security-contract.ts +0 -47
- package/src/security-fix.ts +0 -71
- package/src/send.test.ts +0 -534
- package/src/send.ts +0 -292
- package/src/session-contract.test.ts +0 -31
- package/src/session-contract.ts +0 -43
- package/src/session-errors.ts +0 -125
- package/src/session-route.test.ts +0 -41
- package/src/session-route.ts +0 -32
- package/src/session.runtime.ts +0 -8
- package/src/session.test.ts +0 -559
- package/src/session.ts +0 -330
- package/src/setup-core.ts +0 -52
- package/src/setup-finalize.ts +0 -446
- package/src/setup-surface.test.ts +0 -367
- package/src/setup-surface.ts +0 -69
- package/src/setup-test-helpers.ts +0 -216
- package/src/shared.ts +0 -291
- package/src/socket-timing.test.ts +0 -49
- package/src/socket-timing.ts +0 -38
- package/src/state-migrations.ts +0 -54
- package/src/status-issues.test.ts +0 -137
- package/src/status-issues.ts +0 -185
- package/src/system-prompt.test.ts +0 -199
- package/src/system-prompt.ts +0 -31
- package/src/targets-runtime.ts +0 -180
- package/src/test-helpers.ts +0 -690
- package/src/text-runtime.test.ts +0 -162
- package/src/text-runtime.ts +0 -11
- package/src/vcard.ts +0 -84
- package/targets.ts +0 -5
- package/test-api.ts +0 -2
- package/tsconfig.json +0 -16
package/src/monitor-inbox.blocks-messages-from-unauthorized-senders-not-allowfrom.test-support.ts
DELETED
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
import "./monitor-inbox.test-harness.js";
|
|
2
|
-
import { describe, expect, it, vi } from "vitest";
|
|
3
|
-
import {
|
|
4
|
-
DEFAULT_ACCOUNT_ID,
|
|
5
|
-
expectPairingPromptSent,
|
|
6
|
-
getAuthDir,
|
|
7
|
-
getMonitorWebInbox,
|
|
8
|
-
getSock,
|
|
9
|
-
installWebMonitorInboxUnitTestHooks,
|
|
10
|
-
mockLoadConfig,
|
|
11
|
-
settleInboundWork,
|
|
12
|
-
} from "./monitor-inbox.test-harness.js";
|
|
13
|
-
|
|
14
|
-
const nowSeconds = (offsetMs = 0) => Math.floor((Date.now() + offsetMs) / 1000);
|
|
15
|
-
const DEFAULT_MESSAGES_CFG = {
|
|
16
|
-
messagePrefix: undefined,
|
|
17
|
-
responsePrefix: undefined,
|
|
18
|
-
} as const;
|
|
19
|
-
const TIMESTAMP_OFF_MESSAGES_CFG = {
|
|
20
|
-
...DEFAULT_MESSAGES_CFG,
|
|
21
|
-
timestampPrefix: false,
|
|
22
|
-
} as const;
|
|
23
|
-
|
|
24
|
-
const createNotifyUpsert = (message: Record<string, unknown>) => ({
|
|
25
|
-
type: "notify",
|
|
26
|
-
messages: [message],
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const createDmMessage = (params: { id: string; remoteJid: string; conversation: string }) => ({
|
|
30
|
-
key: {
|
|
31
|
-
id: params.id,
|
|
32
|
-
fromMe: false,
|
|
33
|
-
remoteJid: params.remoteJid,
|
|
34
|
-
},
|
|
35
|
-
message: { conversation: params.conversation },
|
|
36
|
-
messageTimestamp: nowSeconds(),
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const createGroupMessage = (params: {
|
|
40
|
-
id: string;
|
|
41
|
-
remoteJid?: string;
|
|
42
|
-
participant: string;
|
|
43
|
-
conversation: string;
|
|
44
|
-
}) => ({
|
|
45
|
-
key: {
|
|
46
|
-
id: params.id,
|
|
47
|
-
fromMe: false,
|
|
48
|
-
remoteJid: params.remoteJid ?? "11111@g.us",
|
|
49
|
-
participant: params.participant,
|
|
50
|
-
},
|
|
51
|
-
message: { conversation: params.conversation },
|
|
52
|
-
messageTimestamp: nowSeconds(),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
async function startWebInboxMonitor(params: {
|
|
56
|
-
config?: Record<string, unknown>;
|
|
57
|
-
sendReadReceipts?: boolean;
|
|
58
|
-
}) {
|
|
59
|
-
const monitorWebInbox = getMonitorWebInbox();
|
|
60
|
-
if (params.config) {
|
|
61
|
-
mockLoadConfig.mockReturnValue(params.config);
|
|
62
|
-
}
|
|
63
|
-
const onMessage = vi.fn();
|
|
64
|
-
const base = {
|
|
65
|
-
cfg: (params.config ?? mockLoadConfig()) as never,
|
|
66
|
-
verbose: false,
|
|
67
|
-
accountId: DEFAULT_ACCOUNT_ID,
|
|
68
|
-
authDir: getAuthDir(),
|
|
69
|
-
onMessage,
|
|
70
|
-
};
|
|
71
|
-
const listener = await monitorWebInbox(
|
|
72
|
-
params.sendReadReceipts === undefined
|
|
73
|
-
? base
|
|
74
|
-
: {
|
|
75
|
-
...base,
|
|
76
|
-
sendReadReceipts: params.sendReadReceipts,
|
|
77
|
-
},
|
|
78
|
-
);
|
|
79
|
-
return { onMessage, listener, sock: getSock() };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
describe("web monitor inbox", () => {
|
|
83
|
-
installWebMonitorInboxUnitTestHooks();
|
|
84
|
-
|
|
85
|
-
it("blocks messages from unauthorized senders not in allowFrom", async () => {
|
|
86
|
-
// Test for auto-recovery fix: early allowFrom filtering prevents Bad MAC errors
|
|
87
|
-
// from unauthorized senders corrupting sessions
|
|
88
|
-
const config = {
|
|
89
|
-
channels: {
|
|
90
|
-
whatsapp: {
|
|
91
|
-
// Only allow +111
|
|
92
|
-
allowFrom: ["+111"],
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
messages: DEFAULT_MESSAGES_CFG,
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
99
|
-
config,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Message from unauthorized sender +999 (not in allowFrom)
|
|
103
|
-
sock.ev.emit(
|
|
104
|
-
"messages.upsert",
|
|
105
|
-
createNotifyUpsert(
|
|
106
|
-
createDmMessage({
|
|
107
|
-
id: "unauth1",
|
|
108
|
-
remoteJid: "999@s.whatsapp.net",
|
|
109
|
-
conversation: "unauthorized message",
|
|
110
|
-
}),
|
|
111
|
-
),
|
|
112
|
-
);
|
|
113
|
-
await settleInboundWork();
|
|
114
|
-
|
|
115
|
-
// Should NOT call onMessage for unauthorized senders
|
|
116
|
-
expect(onMessage).not.toHaveBeenCalled();
|
|
117
|
-
// Should NOT send read receipts for blocked senders (privacy + avoids Baileys Bad MAC churn).
|
|
118
|
-
expect(sock.readMessages).not.toHaveBeenCalled();
|
|
119
|
-
expectPairingPromptSent(sock, "999@s.whatsapp.net", "+999");
|
|
120
|
-
|
|
121
|
-
await listener.close();
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it("skips read receipts in self-chat mode", async () => {
|
|
125
|
-
const config = {
|
|
126
|
-
channels: {
|
|
127
|
-
whatsapp: {
|
|
128
|
-
// Self-chat heuristic: allowFrom includes selfE164 (+123).
|
|
129
|
-
allowFrom: ["+123"],
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
messages: DEFAULT_MESSAGES_CFG,
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
136
|
-
config,
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
sock.ev.emit(
|
|
140
|
-
"messages.upsert",
|
|
141
|
-
createNotifyUpsert(
|
|
142
|
-
createDmMessage({
|
|
143
|
-
id: "self1",
|
|
144
|
-
remoteJid: "123@s.whatsapp.net",
|
|
145
|
-
conversation: "self ping",
|
|
146
|
-
}),
|
|
147
|
-
),
|
|
148
|
-
);
|
|
149
|
-
await settleInboundWork();
|
|
150
|
-
|
|
151
|
-
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
152
|
-
expect(onMessage).toHaveBeenCalledWith(
|
|
153
|
-
expect.objectContaining({
|
|
154
|
-
from: "+123",
|
|
155
|
-
to: "+123",
|
|
156
|
-
body: "self ping",
|
|
157
|
-
accessControlPassed: true,
|
|
158
|
-
}),
|
|
159
|
-
);
|
|
160
|
-
expect(sock.readMessages).not.toHaveBeenCalled();
|
|
161
|
-
|
|
162
|
-
await listener.close();
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it("skips read receipts when disabled", async () => {
|
|
166
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
167
|
-
sendReadReceipts: false,
|
|
168
|
-
});
|
|
169
|
-
sock.ev.emit(
|
|
170
|
-
"messages.upsert",
|
|
171
|
-
createNotifyUpsert(
|
|
172
|
-
createDmMessage({
|
|
173
|
-
id: "rr-off-1",
|
|
174
|
-
remoteJid: "222@s.whatsapp.net",
|
|
175
|
-
conversation: "read receipts off",
|
|
176
|
-
}),
|
|
177
|
-
),
|
|
178
|
-
);
|
|
179
|
-
await settleInboundWork();
|
|
180
|
-
|
|
181
|
-
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
182
|
-
expect(sock.readMessages).not.toHaveBeenCalled();
|
|
183
|
-
|
|
184
|
-
await listener.close();
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("lets group messages through even when sender not in allowFrom", async () => {
|
|
188
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
189
|
-
config: {
|
|
190
|
-
channels: { whatsapp: { allowFrom: ["+1234"], groupPolicy: "open" } },
|
|
191
|
-
messages: DEFAULT_MESSAGES_CFG,
|
|
192
|
-
},
|
|
193
|
-
});
|
|
194
|
-
sock.ev.emit(
|
|
195
|
-
"messages.upsert",
|
|
196
|
-
createNotifyUpsert(
|
|
197
|
-
createGroupMessage({
|
|
198
|
-
id: "grp3",
|
|
199
|
-
participant: "999@s.whatsapp.net",
|
|
200
|
-
conversation: "unauthorized group message",
|
|
201
|
-
}),
|
|
202
|
-
),
|
|
203
|
-
);
|
|
204
|
-
await settleInboundWork();
|
|
205
|
-
|
|
206
|
-
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
207
|
-
const payload = onMessage.mock.calls[0][0];
|
|
208
|
-
expect(payload.chatType).toBe("group");
|
|
209
|
-
expect(payload.senderE164).toBe("+999");
|
|
210
|
-
|
|
211
|
-
await listener.close();
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it("blocks all group messages when groupPolicy is 'disabled'", async () => {
|
|
215
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
216
|
-
config: {
|
|
217
|
-
channels: { whatsapp: { allowFrom: ["+1234"], groupPolicy: "disabled" } },
|
|
218
|
-
messages: TIMESTAMP_OFF_MESSAGES_CFG,
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
sock.ev.emit(
|
|
222
|
-
"messages.upsert",
|
|
223
|
-
createNotifyUpsert(
|
|
224
|
-
createGroupMessage({
|
|
225
|
-
id: "grp-disabled",
|
|
226
|
-
participant: "999@s.whatsapp.net",
|
|
227
|
-
conversation: "group message should be blocked",
|
|
228
|
-
}),
|
|
229
|
-
),
|
|
230
|
-
);
|
|
231
|
-
await settleInboundWork();
|
|
232
|
-
|
|
233
|
-
// Should NOT call onMessage because groupPolicy is disabled
|
|
234
|
-
expect(onMessage).not.toHaveBeenCalled();
|
|
235
|
-
|
|
236
|
-
await listener.close();
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
it("blocks group messages from senders not in groupAllowFrom when groupPolicy is 'allowlist'", async () => {
|
|
240
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
241
|
-
config: {
|
|
242
|
-
channels: {
|
|
243
|
-
whatsapp: {
|
|
244
|
-
groupAllowFrom: ["+1234"], // Does not include +999
|
|
245
|
-
groupPolicy: "allowlist",
|
|
246
|
-
},
|
|
247
|
-
},
|
|
248
|
-
messages: TIMESTAMP_OFF_MESSAGES_CFG,
|
|
249
|
-
},
|
|
250
|
-
});
|
|
251
|
-
sock.ev.emit(
|
|
252
|
-
"messages.upsert",
|
|
253
|
-
createNotifyUpsert(
|
|
254
|
-
createGroupMessage({
|
|
255
|
-
id: "grp-allowlist-blocked",
|
|
256
|
-
participant: "999@s.whatsapp.net",
|
|
257
|
-
conversation: "unauthorized group sender",
|
|
258
|
-
}),
|
|
259
|
-
),
|
|
260
|
-
);
|
|
261
|
-
await settleInboundWork();
|
|
262
|
-
|
|
263
|
-
// Should NOT call onMessage because sender +999 not in groupAllowFrom
|
|
264
|
-
expect(onMessage).not.toHaveBeenCalled();
|
|
265
|
-
|
|
266
|
-
await listener.close();
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
it("allows group messages from senders in groupAllowFrom when groupPolicy is 'allowlist'", async () => {
|
|
270
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
271
|
-
config: {
|
|
272
|
-
channels: {
|
|
273
|
-
whatsapp: {
|
|
274
|
-
groupAllowFrom: ["+15551234567"], // Includes the sender
|
|
275
|
-
groupPolicy: "allowlist",
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
messages: TIMESTAMP_OFF_MESSAGES_CFG,
|
|
279
|
-
},
|
|
280
|
-
});
|
|
281
|
-
sock.ev.emit(
|
|
282
|
-
"messages.upsert",
|
|
283
|
-
createNotifyUpsert(
|
|
284
|
-
createGroupMessage({
|
|
285
|
-
id: "grp-allowlist-allowed",
|
|
286
|
-
participant: "15551234567@s.whatsapp.net",
|
|
287
|
-
conversation: "authorized group sender",
|
|
288
|
-
}),
|
|
289
|
-
),
|
|
290
|
-
);
|
|
291
|
-
await settleInboundWork();
|
|
292
|
-
|
|
293
|
-
// Should call onMessage because sender is in groupAllowFrom
|
|
294
|
-
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
295
|
-
const payload = onMessage.mock.calls[0][0];
|
|
296
|
-
expect(payload.chatType).toBe("group");
|
|
297
|
-
expect(payload.senderE164).toBe("+15551234567");
|
|
298
|
-
|
|
299
|
-
await listener.close();
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it("allows all group senders with wildcard in groupPolicy allowlist", async () => {
|
|
303
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
304
|
-
config: {
|
|
305
|
-
channels: {
|
|
306
|
-
whatsapp: {
|
|
307
|
-
groupAllowFrom: ["*"], // Wildcard allows everyone
|
|
308
|
-
groupPolicy: "allowlist",
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
messages: TIMESTAMP_OFF_MESSAGES_CFG,
|
|
312
|
-
},
|
|
313
|
-
});
|
|
314
|
-
sock.ev.emit(
|
|
315
|
-
"messages.upsert",
|
|
316
|
-
createNotifyUpsert(
|
|
317
|
-
createGroupMessage({
|
|
318
|
-
id: "grp-wildcard-test",
|
|
319
|
-
remoteJid: "22222@g.us",
|
|
320
|
-
participant: "9999999999@s.whatsapp.net",
|
|
321
|
-
conversation: "wildcard group sender",
|
|
322
|
-
}),
|
|
323
|
-
),
|
|
324
|
-
);
|
|
325
|
-
await settleInboundWork();
|
|
326
|
-
|
|
327
|
-
// Should call onMessage because wildcard allows all senders
|
|
328
|
-
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
329
|
-
const payload = onMessage.mock.calls[0][0];
|
|
330
|
-
expect(payload.chatType).toBe("group");
|
|
331
|
-
|
|
332
|
-
await listener.close();
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
it("blocks group messages when groupPolicy allowlist has no groupAllowFrom", async () => {
|
|
336
|
-
const { onMessage, listener, sock } = await startWebInboxMonitor({
|
|
337
|
-
config: {
|
|
338
|
-
channels: {
|
|
339
|
-
whatsapp: {
|
|
340
|
-
groupPolicy: "allowlist",
|
|
341
|
-
},
|
|
342
|
-
},
|
|
343
|
-
messages: TIMESTAMP_OFF_MESSAGES_CFG,
|
|
344
|
-
},
|
|
345
|
-
});
|
|
346
|
-
sock.ev.emit(
|
|
347
|
-
"messages.upsert",
|
|
348
|
-
createNotifyUpsert(
|
|
349
|
-
createGroupMessage({
|
|
350
|
-
id: "grp-allowlist-empty",
|
|
351
|
-
participant: "999@s.whatsapp.net",
|
|
352
|
-
conversation: "blocked by empty allowlist",
|
|
353
|
-
}),
|
|
354
|
-
),
|
|
355
|
-
);
|
|
356
|
-
await settleInboundWork();
|
|
357
|
-
|
|
358
|
-
expect(onMessage).not.toHaveBeenCalled();
|
|
359
|
-
|
|
360
|
-
await listener.close();
|
|
361
|
-
});
|
|
362
|
-
});
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import "./monitor-inbox.test-harness.js";
|
|
2
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
-
import {
|
|
4
|
-
DEFAULT_ACCOUNT_ID,
|
|
5
|
-
getAuthDir,
|
|
6
|
-
getMonitorWebInbox,
|
|
7
|
-
getSock,
|
|
8
|
-
installWebMonitorInboxUnitTestHooks,
|
|
9
|
-
mockLoadConfig,
|
|
10
|
-
} from "./monitor-inbox.test-harness.js";
|
|
11
|
-
let monitorWebInbox: typeof import("./inbound.js").monitorWebInbox;
|
|
12
|
-
const inboundLoggerInfoMock = vi.hoisted(() => vi.fn());
|
|
13
|
-
|
|
14
|
-
vi.mock("openclaw/plugin-sdk/text-runtime", async () => {
|
|
15
|
-
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/text-runtime")>(
|
|
16
|
-
"openclaw/plugin-sdk/text-runtime",
|
|
17
|
-
);
|
|
18
|
-
return {
|
|
19
|
-
...actual,
|
|
20
|
-
getChildLogger: () => ({
|
|
21
|
-
info: inboundLoggerInfoMock,
|
|
22
|
-
warn: vi.fn(),
|
|
23
|
-
error: vi.fn(),
|
|
24
|
-
debug: vi.fn(),
|
|
25
|
-
}),
|
|
26
|
-
};
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe("web monitor inbox", () => {
|
|
30
|
-
installWebMonitorInboxUnitTestHooks();
|
|
31
|
-
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
inboundLoggerInfoMock.mockReset();
|
|
34
|
-
monitorWebInbox = getMonitorWebInbox();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
async function openMonitor(onMessage = vi.fn()) {
|
|
38
|
-
return await monitorWebInbox({
|
|
39
|
-
cfg: mockLoadConfig() as never,
|
|
40
|
-
verbose: false,
|
|
41
|
-
accountId: DEFAULT_ACCOUNT_ID,
|
|
42
|
-
authDir: getAuthDir(),
|
|
43
|
-
onMessage,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function runSingleUpsertAndCapture(upsert: unknown) {
|
|
48
|
-
const onMessage = vi.fn();
|
|
49
|
-
const listener = await openMonitor(onMessage);
|
|
50
|
-
const sock = getSock();
|
|
51
|
-
sock.ev.emit("messages.upsert", upsert);
|
|
52
|
-
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
53
|
-
return { onMessage, listener, sock };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function expectSingleGroupMessage(
|
|
57
|
-
onMessage: ReturnType<typeof vi.fn>,
|
|
58
|
-
expected: Record<string, unknown>,
|
|
59
|
-
) {
|
|
60
|
-
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
61
|
-
expect(onMessage).toHaveBeenCalledWith(expect.objectContaining(expected));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
it("captures media path for image messages", async () => {
|
|
65
|
-
const { onMessage, listener, sock } = await runSingleUpsertAndCapture({
|
|
66
|
-
type: "notify",
|
|
67
|
-
messages: [
|
|
68
|
-
{
|
|
69
|
-
key: { id: "med1", fromMe: false, remoteJid: "888@s.whatsapp.net" },
|
|
70
|
-
message: { imageMessage: { mimetype: "image/jpeg" } },
|
|
71
|
-
messageTimestamp: 1_700_000_100,
|
|
72
|
-
},
|
|
73
|
-
],
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
expect(onMessage).toHaveBeenCalledWith(
|
|
77
|
-
expect.objectContaining({
|
|
78
|
-
body: "<media:image>",
|
|
79
|
-
}),
|
|
80
|
-
);
|
|
81
|
-
expect(sock.readMessages).toHaveBeenCalledWith([
|
|
82
|
-
{
|
|
83
|
-
remoteJid: "888@s.whatsapp.net",
|
|
84
|
-
id: "med1",
|
|
85
|
-
participant: undefined,
|
|
86
|
-
fromMe: false,
|
|
87
|
-
},
|
|
88
|
-
]);
|
|
89
|
-
expect(sock.sendPresenceUpdate).toHaveBeenNthCalledWith(1, "available");
|
|
90
|
-
await listener.close();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("sets gifPlayback on outbound video payloads when requested", async () => {
|
|
94
|
-
const onMessage = vi.fn();
|
|
95
|
-
const listener = await openMonitor(onMessage);
|
|
96
|
-
const sock = getSock();
|
|
97
|
-
const buf = Buffer.from("gifvid");
|
|
98
|
-
|
|
99
|
-
await listener.sendMessage("+1555", "gif", buf, "video/mp4", {
|
|
100
|
-
gifPlayback: true,
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
expect(sock.sendMessage).toHaveBeenCalledWith("1555@s.whatsapp.net", {
|
|
104
|
-
video: buf,
|
|
105
|
-
caption: "gif",
|
|
106
|
-
mimetype: "video/mp4",
|
|
107
|
-
gifPlayback: true,
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
await listener.close();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it("resolves onClose when the socket closes", async () => {
|
|
114
|
-
const listener = await openMonitor(vi.fn());
|
|
115
|
-
const sock = getSock();
|
|
116
|
-
const reasonPromise = listener.onClose;
|
|
117
|
-
sock.ev.emit("connection.update", {
|
|
118
|
-
connection: "close",
|
|
119
|
-
lastDisconnect: { error: { output: { statusCode: 500 } } },
|
|
120
|
-
});
|
|
121
|
-
await expect(reasonPromise).resolves.toEqual(
|
|
122
|
-
expect.objectContaining({ status: 500, isLoggedOut: false }),
|
|
123
|
-
);
|
|
124
|
-
await listener.close();
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("detaches inbound listeners and ends the socket on close()", async () => {
|
|
128
|
-
const listener = await openMonitor(vi.fn());
|
|
129
|
-
const sock = getSock();
|
|
130
|
-
|
|
131
|
-
expect(sock.ev.listenerCount("messages.upsert")).toBeGreaterThan(0);
|
|
132
|
-
expect(sock.ev.listenerCount("connection.update")).toBeGreaterThan(0);
|
|
133
|
-
|
|
134
|
-
await listener.close();
|
|
135
|
-
|
|
136
|
-
expect(sock.ev.listenerCount("messages.upsert")).toBe(0);
|
|
137
|
-
expect(sock.ev.listenerCount("connection.update")).toBe(0);
|
|
138
|
-
expect(sock.end).toHaveBeenCalledTimes(1);
|
|
139
|
-
expect(sock.end).toHaveBeenCalledWith(expect.any(Error));
|
|
140
|
-
expect(sock.ws.close).not.toHaveBeenCalled();
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("logs inbound bodies through the inbound child logger", async () => {
|
|
144
|
-
const { listener } = await runSingleUpsertAndCapture({
|
|
145
|
-
type: "notify",
|
|
146
|
-
messages: [
|
|
147
|
-
{
|
|
148
|
-
key: { id: "abc", fromMe: false, remoteJid: "999@s.whatsapp.net" },
|
|
149
|
-
message: { conversation: "ping" },
|
|
150
|
-
messageTimestamp: 1_700_000_000,
|
|
151
|
-
pushName: "Tester",
|
|
152
|
-
},
|
|
153
|
-
],
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
expect(inboundLoggerInfoMock).toHaveBeenCalledWith(
|
|
157
|
-
expect.objectContaining({
|
|
158
|
-
body: "ping",
|
|
159
|
-
from: "+999",
|
|
160
|
-
}),
|
|
161
|
-
"inbound message",
|
|
162
|
-
);
|
|
163
|
-
await listener.close();
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("includes participant when marking group messages read", async () => {
|
|
167
|
-
const { listener, sock } = await runSingleUpsertAndCapture({
|
|
168
|
-
type: "notify",
|
|
169
|
-
messages: [
|
|
170
|
-
{
|
|
171
|
-
key: {
|
|
172
|
-
id: "grp1",
|
|
173
|
-
fromMe: false,
|
|
174
|
-
remoteJid: "12345-67890@g.us",
|
|
175
|
-
participant: "111@s.whatsapp.net",
|
|
176
|
-
},
|
|
177
|
-
message: { conversation: "group ping" },
|
|
178
|
-
},
|
|
179
|
-
],
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
expect(sock.readMessages).toHaveBeenCalledWith([
|
|
183
|
-
{
|
|
184
|
-
remoteJid: "12345-67890@g.us",
|
|
185
|
-
id: "grp1",
|
|
186
|
-
participant: "111@s.whatsapp.net",
|
|
187
|
-
fromMe: false,
|
|
188
|
-
},
|
|
189
|
-
]);
|
|
190
|
-
await listener.close();
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it("passes through group messages with participant metadata", async () => {
|
|
194
|
-
const { onMessage, listener } = await runSingleUpsertAndCapture({
|
|
195
|
-
type: "notify",
|
|
196
|
-
messages: [
|
|
197
|
-
{
|
|
198
|
-
key: {
|
|
199
|
-
id: "grp2",
|
|
200
|
-
fromMe: false,
|
|
201
|
-
remoteJid: "99999@g.us",
|
|
202
|
-
participant: "777@s.whatsapp.net",
|
|
203
|
-
},
|
|
204
|
-
pushName: "Alice",
|
|
205
|
-
message: {
|
|
206
|
-
extendedTextMessage: {
|
|
207
|
-
text: "@bot ping",
|
|
208
|
-
contextInfo: { mentionedJid: ["123@s.whatsapp.net"] },
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
messageTimestamp: 1_700_000_000,
|
|
212
|
-
},
|
|
213
|
-
],
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
expect(onMessage).toHaveBeenCalledWith(
|
|
217
|
-
expect.objectContaining({
|
|
218
|
-
chatType: "group",
|
|
219
|
-
conversationId: "99999@g.us",
|
|
220
|
-
senderE164: "+777",
|
|
221
|
-
mentionedJids: ["123@s.whatsapp.net"],
|
|
222
|
-
}),
|
|
223
|
-
);
|
|
224
|
-
await listener.close();
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it("unwraps ephemeral messages, preserves mentions, and still delivers group pings", async () => {
|
|
228
|
-
const { onMessage, listener } = await runSingleUpsertAndCapture({
|
|
229
|
-
type: "notify",
|
|
230
|
-
messages: [
|
|
231
|
-
{
|
|
232
|
-
key: {
|
|
233
|
-
id: "grp-ephem",
|
|
234
|
-
fromMe: false,
|
|
235
|
-
remoteJid: "424242@g.us",
|
|
236
|
-
participant: "888@s.whatsapp.net",
|
|
237
|
-
},
|
|
238
|
-
message: {
|
|
239
|
-
ephemeralMessage: {
|
|
240
|
-
message: {
|
|
241
|
-
extendedTextMessage: {
|
|
242
|
-
text: "oh hey @Clawd UK !",
|
|
243
|
-
contextInfo: { mentionedJid: ["123@s.whatsapp.net"] },
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
},
|
|
248
|
-
},
|
|
249
|
-
],
|
|
250
|
-
});
|
|
251
|
-
expectSingleGroupMessage(onMessage, {
|
|
252
|
-
chatType: "group",
|
|
253
|
-
conversationId: "424242@g.us",
|
|
254
|
-
body: "oh hey @Clawd UK !",
|
|
255
|
-
mentionedJids: ["123@s.whatsapp.net"],
|
|
256
|
-
senderE164: "+888",
|
|
257
|
-
});
|
|
258
|
-
await listener.close();
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it("still forwards group messages (with sender info) even when allowFrom is restrictive", async () => {
|
|
262
|
-
mockLoadConfig.mockReturnValue({
|
|
263
|
-
channels: {
|
|
264
|
-
whatsapp: {
|
|
265
|
-
// does not include +777
|
|
266
|
-
allowFrom: ["+111"],
|
|
267
|
-
groupPolicy: "open",
|
|
268
|
-
},
|
|
269
|
-
},
|
|
270
|
-
messages: {
|
|
271
|
-
messagePrefix: undefined,
|
|
272
|
-
responsePrefix: undefined,
|
|
273
|
-
},
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
const { onMessage, listener } = await runSingleUpsertAndCapture({
|
|
277
|
-
type: "notify",
|
|
278
|
-
messages: [
|
|
279
|
-
{
|
|
280
|
-
key: {
|
|
281
|
-
id: "grp-allow",
|
|
282
|
-
fromMe: false,
|
|
283
|
-
remoteJid: "55555@g.us",
|
|
284
|
-
participant: "777@s.whatsapp.net",
|
|
285
|
-
},
|
|
286
|
-
message: {
|
|
287
|
-
extendedTextMessage: {
|
|
288
|
-
text: "@bot hi",
|
|
289
|
-
contextInfo: { mentionedJid: ["123@s.whatsapp.net"] },
|
|
290
|
-
},
|
|
291
|
-
},
|
|
292
|
-
},
|
|
293
|
-
],
|
|
294
|
-
});
|
|
295
|
-
expectSingleGroupMessage(onMessage, {
|
|
296
|
-
chatType: "group",
|
|
297
|
-
from: "55555@g.us",
|
|
298
|
-
senderE164: "+777",
|
|
299
|
-
senderJid: "777@s.whatsapp.net",
|
|
300
|
-
mentionedJids: ["123@s.whatsapp.net"],
|
|
301
|
-
selfE164: "+123",
|
|
302
|
-
selfJid: "123@s.whatsapp.net",
|
|
303
|
-
});
|
|
304
|
-
await listener.close();
|
|
305
|
-
});
|
|
306
|
-
});
|