@oxidezap/baileyrs 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +60 -0
  2. package/lib/Bridge/primitives.d.ts +49 -3
  3. package/lib/Bridge/primitives.js +126 -8
  4. package/lib/Bridge/schema.js +208 -87
  5. package/lib/Bridge/types.d.ts +61 -2
  6. package/lib/Compatibility/derived-stanza-nodes.d.ts +28 -0
  7. package/lib/Compatibility/derived-stanza-nodes.js +71 -0
  8. package/lib/Compatibility/encode-proto.d.ts +17 -0
  9. package/lib/Compatibility/encode-proto.js +32 -0
  10. package/lib/Compatibility/proto-runtime.d.ts +10 -0
  11. package/lib/Compatibility/proto-runtime.js +176 -11
  12. package/lib/Defaults/index.d.ts +6 -0
  13. package/lib/Defaults/index.js +6 -0
  14. package/lib/Socket/blocking.d.ts +3 -1
  15. package/lib/Socket/blocking.js +3 -0
  16. package/lib/Socket/communities.d.ts +14 -9
  17. package/lib/Socket/communities.js +24 -5
  18. package/lib/Socket/contacts.d.ts +3 -1
  19. package/lib/Socket/contacts.js +3 -0
  20. package/lib/Socket/events.js +35 -6
  21. package/lib/Socket/groups.d.ts +30 -4
  22. package/lib/Socket/groups.js +20 -4
  23. package/lib/Socket/index.d.ts +18 -17
  24. package/lib/Socket/index.js +18 -6
  25. package/lib/Socket/messages.js +18 -7
  26. package/lib/Socket/newsletter.d.ts +3 -1
  27. package/lib/Socket/newsletter.js +3 -3
  28. package/lib/Socket/presence.d.ts +3 -2
  29. package/lib/Socket/presence.js +4 -0
  30. package/lib/Socket/privacy.d.ts +7 -1
  31. package/lib/Socket/privacy.js +16 -0
  32. package/lib/Socket/server-queries.d.ts +3 -1
  33. package/lib/Socket/server-queries.js +3 -0
  34. package/lib/Types/Auth.d.ts +4 -1
  35. package/lib/Types/Chat.d.ts +26 -8
  36. package/lib/Types/Chat.js +18 -0
  37. package/lib/Types/Events.d.ts +17 -0
  38. package/lib/Types/GroupMetadata.d.ts +3 -1
  39. package/lib/Types/GroupMetadata.js +1 -1
  40. package/lib/Types/Message.d.ts +20 -2
  41. package/lib/Types/Message.js +11 -0
  42. package/lib/Utils/argument-domain.d.ts +15 -0
  43. package/lib/Utils/argument-domain.js +36 -0
  44. package/lib/Utils/event-buffer.js +48 -11
  45. package/lib/Utils/messages.d.ts +3 -1
  46. package/lib/Utils/messages.js +35 -7
  47. package/lib/Utils/process-history-message.d.ts +11 -2
  48. package/lib/Utils/process-history-message.js +11 -7
  49. package/lib/Utils/use-multi-file-auth-state.js +45 -0
  50. package/package.json +9 -3
@@ -1,14 +1,40 @@
1
1
  import { type GroupMetadata, type ParticipantAction, type WAMessageKey } from '../Types/index.js';
2
2
  import { proto } from '../WAProto/runtime.js';
3
3
  import type { SocketContext } from './types.js';
4
- type GroupSetting = 'announcement' | 'not_announcement' | 'locked' | 'unlocked';
4
+ declare const GROUP_SETTING_ALIASES: {
5
+ readonly announcement: {
6
+ readonly setting: 'announce';
7
+ readonly value: true;
8
+ };
9
+ readonly not_announcement: {
10
+ readonly setting: 'announce';
11
+ readonly value: false;
12
+ };
13
+ readonly locked: {
14
+ readonly setting: 'locked';
15
+ readonly value: true;
16
+ };
17
+ readonly unlocked: {
18
+ readonly setting: 'locked';
19
+ readonly value: false;
20
+ };
21
+ };
22
+ /** The table is the definition: both the type and the accepted set come off it. */
23
+ export type GroupSetting = keyof typeof GROUP_SETTING_ALIASES;
24
+ export declare const GROUP_SETTINGS: readonly GroupSetting[];
25
+ export declare const GROUP_REQUEST_ACTIONS: readonly ['approve', 'reject'];
26
+ export type GroupRequestAction = (typeof GROUP_REQUEST_ACTIONS)[number];
27
+ export declare const MEMBER_ADD_MODES: readonly ['admin_add', 'all_member_add'];
28
+ export type MemberAddMode = (typeof MEMBER_ADD_MODES)[number];
29
+ export declare const JOIN_APPROVAL_MODES: readonly ['on', 'off'];
30
+ export type JoinApprovalMode = (typeof JOIN_APPROVAL_MODES)[number];
5
31
  export declare const makeGroupMethods: (ctx: SocketContext) => {
6
32
  groupMetadata: (jid: string) => Promise<GroupMetadata>;
7
33
  groupCreate: (subject: string, participants: string[]) => Promise<GroupMetadata>;
8
34
  groupLeave: (id: string) => Promise<void>;
9
35
  groupUpdateSubject: (jid: string, subject: string) => Promise<void>;
10
36
  groupRequestParticipantsList: (jid: string) => Promise<Array<Record<string, string>>>;
11
- groupRequestParticipantsUpdate: (jid: string, participants: string[], action: 'approve' | 'reject') => Promise<import("../Compatibility/socket-results.js").MembershipRequestUpdateResult[]>;
37
+ groupRequestParticipantsUpdate: (jid: string, participants: string[], action: GroupRequestAction) => Promise<import("../Compatibility/socket-results.js").MembershipRequestUpdateResult[]>;
12
38
  groupParticipantsUpdate: (jid: string, participants: string[], action: ParticipantAction) => Promise<import("../Compatibility/socket-results.js").ParticipantUpdateResult[]>;
13
39
  groupUpdateDescription: (jid: string, description?: string) => Promise<void>;
14
40
  groupInviteCode: (jid: string) => Promise<string | undefined>;
@@ -19,8 +45,8 @@ export declare const makeGroupMethods: (ctx: SocketContext) => {
19
45
  groupGetInviteInfo: (code: string) => Promise<GroupMetadata>;
20
46
  groupToggleEphemeral: (jid: string, ephemeralExpiration: number) => Promise<void>;
21
47
  groupSettingUpdate: (jid: string, setting: GroupSetting) => Promise<void>;
22
- groupMemberAddMode: (jid: string, mode: 'admin_add' | 'all_member_add') => Promise<void>;
23
- groupJoinApprovalMode: (jid: string, mode: 'on' | 'off') => Promise<void>;
48
+ groupMemberAddMode: (jid: string, mode: MemberAddMode) => Promise<void>;
49
+ groupJoinApprovalMode: (jid: string, mode: JoinApprovalMode) => Promise<void>;
24
50
  groupFetchAllParticipating: () => Promise<Record<string, GroupMetadata>>;
25
51
  updateMemberLabel: (jid: string, memberLabel: string) => Promise<string>;
26
52
  };
@@ -1,7 +1,8 @@
1
1
  import { bridgeInviteLinkToCode, bridgeMembershipRequestsToBaileys, bridgeMembershipRequestUpdatesToBaileys, bridgeParticipantChangesToBaileys } from '../Compatibility/socket-results.js';
2
2
  import { emitMessageUpsert } from '../Compatibility/message-upsert.js';
3
- import { WAMessageStubType } from '../Types/index.js';
4
- import { generateMessageIDV2, unixTimestampSeconds } from '../Utils/generics.js';
3
+ import { PARTICIPANT_ACTIONS, WAMessageStubType } from '../Types/index.js';
4
+ import { assertArgumentDomain } from '../Utils/argument-domain.js';
5
+ import { generateMessageIDV2, toNumber, unixTimestampSeconds } from '../Utils/generics.js';
5
6
  import { proto } from '../WAProto/runtime.js';
6
7
  import { bridgeGroupMetadataToBaileys } from '../Compatibility/group-metadata.js';
7
8
  const GROUP_SETTING_ALIASES = {
@@ -10,14 +11,23 @@ const GROUP_SETTING_ALIASES = {
10
11
  locked: { setting: 'locked', value: true },
11
12
  unlocked: { setting: 'locked', value: false }
12
13
  };
13
- const inviteExpirationNumber = (value) => typeof value === 'number' ? value : (value?.toNumber() ?? 0);
14
+ export const GROUP_SETTINGS = Object.keys(GROUP_SETTING_ALIASES);
15
+ export const GROUP_REQUEST_ACTIONS = ['approve', 'reject'];
16
+ export const MEMBER_ADD_MODES = ['admin_add', 'all_member_add'];
17
+ export const JOIN_APPROVAL_MODES = ['on', 'off'];
18
+ // `toNumber` rather than calling `.toNumber()`: a 64-bit field now crosses the
19
+ // bridge as a plain `{ low, high, unsigned }` once the value is too wide to be
20
+ // exact as a double, and that shape carries no methods. The helper reads both
21
+ // forms, and reconstructs the high word instead of dropping it.
22
+ const inviteExpirationNumber = (value) => toNumber(value);
14
23
  export const makeGroupMethods = (ctx) => {
15
24
  const groupMetadata = async (jid) => {
16
25
  const metadata = await (await ctx.getClient()).getGroupMetadata(jid);
17
26
  return bridgeGroupMetadataToBaileys(metadata);
18
27
  };
19
28
  const groupSettingUpdate = async (jid, setting) => {
20
- const mapped = GROUP_SETTING_ALIASES[setting];
29
+ const checked = assertArgumentDomain('groupSettingUpdate', 'setting', setting, GROUP_SETTINGS);
30
+ const mapped = GROUP_SETTING_ALIASES[checked];
21
31
  await (await ctx.getClient()).groupSettingUpdate(jid, mapped.setting, mapped.value);
22
32
  };
23
33
  const groupAcceptInviteV4 = ctx.ev.createBufferedFunction(async (key, inviteMessage
@@ -71,9 +81,11 @@ export const makeGroupMethods = (ctx) => {
71
81
  return bridgeMembershipRequestsToBaileys(await (await ctx.getClient()).groupRequestParticipantsList(jid));
72
82
  },
73
83
  groupRequestParticipantsUpdate: async (jid, participants, action) => {
84
+ assertArgumentDomain('groupRequestParticipantsUpdate', 'action', action, GROUP_REQUEST_ACTIONS);
74
85
  return bridgeMembershipRequestUpdatesToBaileys(await (await ctx.getClient()).groupRequestParticipantsUpdate(jid, participants, action));
75
86
  },
76
87
  groupParticipantsUpdate: async (jid, participants, action) => {
88
+ assertArgumentDomain('groupParticipantsUpdate', 'action', action, PARTICIPANT_ACTIONS);
77
89
  return bridgeParticipantChangesToBaileys(await (await ctx.getClient()).groupParticipantsUpdate(jid, participants, action));
78
90
  },
79
91
  groupUpdateDescription: async (jid, description) => {
@@ -100,9 +112,13 @@ export const makeGroupMethods = (ctx) => {
100
112
  },
101
113
  groupSettingUpdate,
102
114
  groupMemberAddMode: async (jid, mode) => {
115
+ assertArgumentDomain('groupMemberAddMode', 'mode', mode, MEMBER_ADD_MODES);
103
116
  await (await ctx.getClient()).groupMemberAddMode(jid, mode);
104
117
  },
105
118
  groupJoinApprovalMode: async (jid, mode) => {
119
+ // Anything but 'on' used to mean off, so a typo turned approvals off
120
+ // and reported success.
121
+ assertArgumentDomain('groupJoinApprovalMode', 'mode', mode, JOIN_APPROVAL_MODES);
106
122
  await (await ctx.getClient()).groupSettingUpdate(jid, 'membership_approval', mode === 'on');
107
123
  },
108
124
  groupFetchAllParticipating: async () => {
@@ -2,15 +2,16 @@ import { Buffer } from 'node:buffer';
2
2
  import { type UploadMediaResult } from '@oxidezap/whatsapp-rust-bridge';
3
3
  import { WebSocketClient } from '../Compatibility/websocket-client.js';
4
4
  import { type MediaType } from '../Defaults/index.js';
5
- import type { BinaryNode, AuthenticationCreds, ConnectionState, Contact, ReachoutTimelockState, SignalKeyStoreWithTransaction, UserFacingSocketConfig, WABusinessProfile, WAMessage, WAMessageKey } from '../Types/index.js';
5
+ import type { BinaryNode, AuthenticationCreds, ConnectionState, Contact, ReachoutTimelockState, SignalKeyStoreWithTransaction, UserFacingSocketConfig, WABusinessProfile, WAMessage, WAMessageKey, WAPresence } from '../Types/index.js';
6
6
  import type Long from 'long';
7
+ import { type MediaDownloadType } from '../Utils/messages.js';
7
8
  import type { MediaDownloadOptions } from '../Utils/messages-media.js';
8
9
  import type { proto } from '../WAProto/runtime.js';
9
10
  /** Build the ws EventEmitter with auto-enable raw node forwarding */
10
11
  declare const makeWASocket: (config: UserFacingSocketConfig) => {
11
12
  sendMessageAck: (node: BinaryNode, errorCode?: number) => Promise<void>;
12
13
  sendRetryRequest: (node: BinaryNode, forceIncludeKeys?: boolean) => Promise<void>;
13
- updateBlockStatus: (jid: string, action: 'block' | 'unblock') => Promise<void>;
14
+ updateBlockStatus: (jid: string, action: import("./blocking.js").BlockAction) => Promise<void>;
14
15
  fetchBlocklist: () => Promise<Array<string | undefined>>;
15
16
  getCatalog: ({ jid, limit, cursor }: import("../index.js").GetCatalogOptions) => Promise<import("../index.js").CatalogPage>;
16
17
  getCollections: (jid?: string, limit?: number) => Promise<import("../index.js").CollectionsPage>;
@@ -40,14 +41,14 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
40
41
  addOrEditQuickReply: (quickReply: import("../Types/Bussines.js").QuickReplyAction) => Promise<void>;
41
42
  removeQuickReply: (timestamp: string) => Promise<void>;
42
43
  onWhatsApp: (...phoneNumber: string[]) => Promise<import("./contacts.js").OnWhatsAppResult[] | undefined>;
43
- profilePictureUrl: (jid: string, type?: 'preview' | 'image', timeoutMs?: number) => Promise<string | undefined>;
44
+ profilePictureUrl: (jid: string, type?: import("./contacts.js").ProfilePictureType, timeoutMs?: number) => Promise<string | undefined>;
44
45
  fetchUserInfo: (...jids: string[]) => Promise<Record<string, import("@oxidezap/whatsapp-rust-bridge").UserInfoResult>>;
45
46
  groupMetadata: (jid: string) => Promise<import("../index.js").GroupMetadata>;
46
47
  groupCreate: (subject: string, participants: string[]) => Promise<import("../index.js").GroupMetadata>;
47
48
  groupLeave: (id: string) => Promise<void>;
48
49
  groupUpdateSubject: (jid: string, subject: string) => Promise<void>;
49
50
  groupRequestParticipantsList: (jid: string) => Promise<Array<Record<string, string>>>;
50
- groupRequestParticipantsUpdate: (jid: string, participants: string[], action: 'approve' | 'reject') => Promise<import("../Compatibility/socket-results.js").MembershipRequestUpdateResult[]>;
51
+ groupRequestParticipantsUpdate: (jid: string, participants: string[], action: import("./groups.js").GroupRequestAction) => Promise<import("../Compatibility/socket-results.js").MembershipRequestUpdateResult[]>;
51
52
  groupParticipantsUpdate: (jid: string, participants: string[], action: import("../index.js").ParticipantAction) => Promise<import("../Compatibility/socket-results.js").ParticipantUpdateResult[]>;
52
53
  groupUpdateDescription: (jid: string, description?: string) => Promise<void>;
53
54
  groupInviteCode: (jid: string) => Promise<string | undefined>;
@@ -57,9 +58,9 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
57
58
  groupAcceptInviteV4: (key: string | WAMessageKey, inviteMessage: proto.Message.IGroupInviteMessage) => Promise<any>;
58
59
  groupGetInviteInfo: (code: string) => Promise<import("../index.js").GroupMetadata>;
59
60
  groupToggleEphemeral: (jid: string, ephemeralExpiration: number) => Promise<void>;
60
- groupSettingUpdate: (jid: string, setting: "announcement" | "locked" | "not_announcement" | "unlocked") => Promise<void>;
61
- groupMemberAddMode: (jid: string, mode: 'admin_add' | 'all_member_add') => Promise<void>;
62
- groupJoinApprovalMode: (jid: string, mode: 'on' | 'off') => Promise<void>;
61
+ groupSettingUpdate: (jid: string, setting: import("./groups.js").GroupSetting) => Promise<void>;
62
+ groupMemberAddMode: (jid: string, mode: import("./groups.js").MemberAddMode) => Promise<void>;
63
+ groupJoinApprovalMode: (jid: string, mode: import("./groups.js").JoinApprovalMode) => Promise<void>;
63
64
  groupFetchAllParticipating: () => Promise<Record<string, import("../index.js").GroupMetadata>>;
64
65
  updateMemberLabel: (jid: string, memberLabel: string) => Promise<string>;
65
66
  communityMetadata: (jid: string) => Promise<import("../index.js").GroupMetadata>;
@@ -81,7 +82,7 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
81
82
  }[];
82
83
  }>;
83
84
  communityRequestParticipantsList: (jid: string) => Promise<Array<Record<string, string>>>;
84
- communityRequestParticipantsUpdate: (jid: string, participants: string[], action: 'approve' | 'reject') => Promise<import("../Compatibility/socket-results.js").MembershipRequestUpdateResult[]>;
85
+ communityRequestParticipantsUpdate: (jid: string, participants: string[], action: import("./groups.js").GroupRequestAction) => Promise<import("../Compatibility/socket-results.js").MembershipRequestUpdateResult[]>;
85
86
  communityParticipantsUpdate: (jid: string, participants: string[], action: import("../index.js").ParticipantAction) => Promise<import("../Compatibility/socket-results.js").ParticipantUpdateResult[]>;
86
87
  communityUpdateDescription: (jid: string, description?: string) => Promise<void>;
87
88
  communityInviteCode: (jid: string) => Promise<string | undefined>;
@@ -91,9 +92,9 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
91
92
  communityAcceptInviteV4: (key: string | WAMessageKey, inviteMessage: proto.Message.IGroupInviteMessage) => Promise<any>;
92
93
  communityGetInviteInfo: (code: string) => Promise<import("../index.js").GroupMetadata>;
93
94
  communityToggleEphemeral: (jid: string, ephemeralExpiration: number) => Promise<void>;
94
- communitySettingUpdate: (jid: string, setting: "announcement" | "locked" | "not_announcement" | "unlocked") => Promise<void>;
95
- communityMemberAddMode: (jid: string, mode: 'admin_add' | 'all_member_add') => Promise<void>;
96
- communityJoinApprovalMode: (jid: string, mode: 'on' | 'off') => Promise<void>;
95
+ communitySettingUpdate: (jid: string, setting: import("./groups.js").GroupSetting) => Promise<void>;
96
+ communityMemberAddMode: (jid: string, mode: import("./groups.js").MemberAddMode) => Promise<void>;
97
+ communityJoinApprovalMode: (jid: string, mode: import("./groups.js").JoinApprovalMode) => Promise<void>;
97
98
  communityFetchAllParticipating: () => Promise<Record<string, import("../index.js").GroupMetadata>>;
98
99
  waitForSocketOpen: () => Promise<void>;
99
100
  upsertMessage: (msg: WAMessage, type: import("../index.js").MessageUpsertType) => Promise<void>;
@@ -111,7 +112,7 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
111
112
  sendReceipts: (keys: WAMessageKey[], type: import("../index.js").MessageReceiptType) => Promise<void>;
112
113
  requestPlaceholderResend: (messageKey: WAMessageKey, msgData?: Partial<WAMessage>) => Promise<string | undefined>;
113
114
  newsletterCreate: (name: string, description?: string) => Promise<import("../index.js").NewsletterMetadata>;
114
- newsletterMetadata: (type: 'invite' | 'jid', key: string) => Promise<import("../index.js").NewsletterMetadata | null>;
115
+ newsletterMetadata: (type: import("./newsletter.js").NewsletterKeyType, key: string) => Promise<import("../index.js").NewsletterMetadata | null>;
115
116
  newsletterUpdate: (jid: string, updates: import("../index.js").NewsletterUpdate) => Promise<import("../index.js").NewsletterMetadata>;
116
117
  newsletterUpdateName: (jid: string, name: string) => Promise<import("../index.js").NewsletterMetadata>;
117
118
  newsletterUpdateDescription: (jid: string, description: string) => Promise<import("../index.js").NewsletterMetadata>;
@@ -139,9 +140,9 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
139
140
  uploadPreKeysToServerIfRequired: () => Promise<void>;
140
141
  digestKeyBundle: () => Promise<void>;
141
142
  rotateSignedPreKey: () => Promise<void>;
142
- sendPresence: (status: 'available' | 'unavailable') => Promise<void>;
143
+ sendPresence: (status: import("../index.js").WAPresenceStatus) => Promise<void>;
143
144
  presenceSubscribe: (toJid: string) => Promise<void>;
144
- sendChatState: (jid: string, state: 'composing' | 'recording' | 'paused') => Promise<void>;
145
+ sendChatState: (jid: string, state: import("../index.js").WAChatState) => Promise<void>;
145
146
  fetchPrivacySettings: (force?: boolean) => Promise<any>;
146
147
  updatePrivacySetting: (category: string, value: string) => Promise<void>;
147
148
  updateLastSeenPrivacy: (value: import("../index.js").WAPrivacyValue) => Promise<void>;
@@ -163,7 +164,7 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
163
164
  fetchNewChatMessageCap: () => Promise<import("../index.js").NewChatMessageCapInfo & {
164
165
  remaining_quota?: number;
165
166
  }>;
166
- cleanDirtyBits: (type: 'account_sync' | 'groups', fromTimestamp?: number | string) => Promise<void>;
167
+ cleanDirtyBits: (type: import("./server-queries.js").DirtyBitType, fromTimestamp?: number | string) => Promise<void>;
167
168
  sendPeerDataOperationMessage: (_pdoMessage: unknown) => Promise<never>;
168
169
  createCallLink: (_type: 'audio' | 'video', _event?: unknown, _timeoutMs?: number) => Promise<never>;
169
170
  requestPairingCode: (phoneNumber: string, customPairingCode?: string) => Promise<string>;
@@ -272,7 +273,7 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
272
273
  * caller hears about the protocol mistake instead of the bridge silently
273
274
  * sending nothing.
274
275
  */
275
- sendPresenceUpdate: (type: 'available' | 'unavailable' | 'composing' | 'recording' | 'paused', toJid?: string) => Promise<void>;
276
+ sendPresenceUpdate: (type: WAPresence, toJid?: string) => Promise<void>;
276
277
  /**
277
278
  * Plaintext media upload helper, source-compatible with the upstream
278
279
  * Baileys `sock.waUploadToServer(buf, { mediaType })` shape so existing
@@ -303,7 +304,7 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
303
304
  getBusinessProfile: (jid: string) => Promise<WABusinessProfile | void>;
304
305
  fetchMessageHistory: (count: number, oldestMsgKey: WAMessageKey, oldestMsgTimestamp: number | Long) => Promise<string>;
305
306
  sendStatusMessage: (message: Record<string, unknown>, recipients: string[]) => Promise<string>;
306
- downloadMedia: <T extends 'buffer' | 'stream'>(message: WAMessage, type: T, options?: MediaDownloadOptions) => Promise<T extends "buffer" ? Buffer<ArrayBufferLike> : import("node:stream").Readable>;
307
+ downloadMedia: <T extends MediaDownloadType>(message: WAMessage, type: T, options?: MediaDownloadOptions) => Promise<T extends "buffer" ? Buffer<ArrayBufferLike> : import("node:stream").Readable>;
307
308
  };
308
309
  export default makeWASocket;
309
310
  //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import { Buffer } from 'node:buffer';
2
2
  import { randomBytes } from 'node:crypto';
3
- import { createWhatsAppClient, encodeProto, initWasmEngine } from '@oxidezap/whatsapp-rust-bridge';
3
+ import { createWhatsAppClient, initWasmEngine } from '@oxidezap/whatsapp-rust-bridge';
4
+ import { encodeProtoCompat } from '../Compatibility/encode-proto.js';
4
5
  import { normalizeSocketAuthenticationState } from '../Compatibility/internal/auth-state.js';
5
6
  import { makeMutex } from '../Compatibility/internal/make-mutex.js';
6
7
  import { isNativeMemoryStore } from '../Compatibility/internal/native-memory-store.js';
@@ -12,11 +13,12 @@ import { makeStanzaResponseMethods } from '../Compatibility/stanza-responses.js'
12
13
  import { makeParticipatingRefreshHandler } from '../Compatibility/participating-refresh.js';
13
14
  import { makeTaggedMessageWaiter } from '../Compatibility/tagged-message-waiter.js';
14
15
  import { isRawNodeForwardingEnabled, WebSocketClient } from '../Compatibility/websocket-client.js';
15
- import { DEFAULT_CONNECTION_CONFIG } from '../Defaults/index.js';
16
- import { DisconnectReason } from '../Types/index.js';
16
+ import { DEFAULT_CONNECTION_CONFIG, MEDIA_TYPES } from '../Defaults/index.js';
17
+ import { DisconnectReason, WA_PRESENCES } from '../Types/index.js';
18
+ import { assertArgumentDomain } from '../Utils/argument-domain.js';
17
19
  import { Boom } from '../Utils/boom.js';
18
20
  import { makeEventBuffer } from '../Utils/event-buffer.js';
19
- import { _registerActiveBridgeClient, _unregisterActiveBridgeClient, downloadMediaMessage } from '../Utils/messages.js';
21
+ import { _registerActiveBridgeClient, _unregisterActiveBridgeClient, downloadMediaMessage, MEDIA_DOWNLOAD_TYPES } from '../Utils/messages.js';
20
22
  import { makeNativeCryptoProvider } from '../Utils/native-crypto-provider.js';
21
23
  import { wrapLegacyStore } from '../Utils/wrap-legacy-store.js';
22
24
  import { assertNodeErrorFree } from '../WABinary/generic-utils.js';
@@ -805,7 +807,7 @@ const makeWASocket = (config) => {
805
807
  if (dsmMessage) {
806
808
  throw new Boom('createParticipantNodes: dsmMessage is not supported, the engine encrypts one payload for every recipient and cannot substitute a different one for your own devices', { statusCode: 501 });
807
809
  }
808
- const bytes = encodeProto('Message', message);
810
+ const bytes = encodeProtoCompat('Message', message);
809
811
  return (await ctx.getClient()).createParticipantNodesBytes(jids, bytes, extraAttrs ?? {});
810
812
  },
811
813
  signalRepository,
@@ -828,6 +830,9 @@ const makeWASocket = (config) => {
828
830
  * sending nothing.
829
831
  */
830
832
  sendPresenceUpdate: async (type, toJid) => {
833
+ // Ahead of the client: an off-union value used to fall through to the
834
+ // chat-state branch and be reported as a missing jid.
835
+ assertArgumentDomain('sendPresenceUpdate', 'type', type, WA_PRESENCES);
831
836
  const c = await ctx.getClient();
832
837
  if (type === 'available' || type === 'unavailable') {
833
838
  return c.sendPresence(type);
@@ -844,6 +849,9 @@ const makeWASocket = (config) => {
844
849
  * keep working. Delegates to the bridge's encrypt + CDN-failover upload.
845
850
  */
846
851
  waUploadToServer: async (data, opts) => {
852
+ // The upstream set, which is wider than what the bridge uploads:
853
+ // `toBridgeMediaType` below still refuses the ones it cannot map.
854
+ assertArgumentDomain('waUploadToServer', 'mediaType', opts?.mediaType, MEDIA_TYPES);
847
855
  const bytes = data instanceof Uint8Array && !Buffer.isBuffer(data) ? data : new Uint8Array(data);
848
856
  return (await ctx.getClient()).uploadMedia(bytes, toBridgeMediaType(opts.mediaType));
849
857
  },
@@ -879,7 +887,7 @@ const makeWASocket = (config) => {
879
887
  return (await ctx.getClient()).fetchMessageHistory(count, oldestMsgKey.remoteJid || '', oldestMsgKey.id || '', oldestMsgKey.fromMe || false, typeof oldestMsgTimestamp === 'number' ? oldestMsgTimestamp : oldestMsgTimestamp.toNumber());
880
888
  },
881
889
  sendStatusMessage: async (message, recipients) => {
882
- const bytes = encodeProto('Message', message);
890
+ const bytes = encodeProtoCompat('Message', message);
883
891
  return (await ctx.getClient()).sendStatusMessageBytes(bytes, recipients);
884
892
  },
885
893
  ...makeMessageMethods(ctx),
@@ -897,6 +905,10 @@ const makeWASocket = (config) => {
897
905
  ...makeBusinessMethods(ctx),
898
906
  ...makeServerQueryMethods(ctx),
899
907
  downloadMedia: async (message, type, options = {}) => {
908
+ // Checked here as well as in the helper: the client is awaited while
909
+ // the context below is built, and a check past that await reports a
910
+ // stack without the caller in it.
911
+ assertArgumentDomain('downloadMedia', 'type', type, MEDIA_DOWNLOAD_TYPES);
900
912
  return downloadMediaMessage(message, type, options, {
901
913
  logger,
902
914
  reuploadRequest: (m) => sock.updateMediaMessage(m),
@@ -1,7 +1,9 @@
1
- import { encodeProto } from '@oxidezap/whatsapp-rust-bridge';
1
+ import { sendDroppingDerivedNodes } from '../Compatibility/derived-stanza-nodes.js';
2
+ import { encodeProtoCompat } from '../Compatibility/encode-proto.js';
2
3
  import { planMessageRelay } from '../Compatibility/message-relay.js';
3
4
  import { receiptMessageKeys } from '../Compatibility/message-keys.js';
4
- import { WAProto } from '../Types/index.js';
5
+ import { MESSAGE_RECEIPT_TYPES, WAProto } from '../Types/index.js';
6
+ import { assertArgumentDomain } from '../Utils/argument-domain.js';
5
7
  import { Boom } from '../Utils/boom.js';
6
8
  import { generateWAMessage, getContentType, normalizeMessageContent } from '../Utils/messages.js';
7
9
  import { jidNormalizedUser } from '../WABinary/index.js';
@@ -68,7 +70,7 @@ export const makeMessageMethods = (ctx) => ({
68
70
  }
69
71
  }
70
72
  let msgId;
71
- const msgBytes = encodeProto('Message', msg);
73
+ const msgBytes = encodeProtoCompat('Message', msg);
72
74
  if (jid === 'status@broadcast' && options?.statusJidList?.length) {
73
75
  msgId = await client.sendStatusMessageBytes(msgBytes, options.statusJidList);
74
76
  }
@@ -137,15 +139,20 @@ export const makeMessageMethods = (ctx) => ({
137
139
  // The message goes to the bridge as the caller built it: the core settles
138
140
  // messageSecret / reportingTokenVersion itself, reusing a caller-set secret
139
141
  // rather than replacing it, so nothing here has to be dropped.
140
- const bytes = encodeProto('Message', message);
142
+ const bytes = encodeProtoCompat('Message', message);
141
143
  if (plan.kind === 'retransmission') {
142
144
  await client.retransmitMessageBytes(jid, bytes, plan.input);
143
145
  return plan.messageId;
144
146
  }
147
+ // Both sends go through the same retry: a caller node the engine derives
148
+ // is refused the same way whether the message is bound for a chat or for
149
+ // status, and the escape hatch — a node it does not derive — survives
150
+ // either way.
151
+ const drop = (tag) => ctx.logger.debug({ jid, messageId: plan.messageId, tag }, 'dropped an additionalNodes entry the engine derives from the message');
145
152
  if (plan.kind === 'status') {
146
- return client.sendStatusMessageBytesWithOptions(bytes, plan.recipients, plan.messageId, plan.nodes, plan.refreshDevices);
153
+ return sendDroppingDerivedNodes(plan.nodes, nodes => client.sendStatusMessageBytesWithOptions(bytes, plan.recipients, plan.messageId, nodes, plan.refreshDevices), drop);
147
154
  }
148
- return client.relayMessageBytesWithOptions(jid, bytes, plan.messageId, plan.nodes, plan.refreshGroupMetadata, plan.refreshDevices);
155
+ return sendDroppingDerivedNodes(plan.nodes, nodes => client.relayMessageBytesWithOptions(jid, bytes, plan.messageId, nodes, plan.refreshGroupMetadata, plan.refreshDevices), drop);
149
156
  },
150
157
  readMessages: async (keys) => {
151
158
  const receiptKeys = receiptMessageKeys(keys);
@@ -161,6 +168,9 @@ export const makeMessageMethods = (ctx) => ({
161
168
  * Not supported: 'hist_sync', 'peer_msg' (logged as warning)
162
169
  */
163
170
  sendReceipt: async (jid, participant, messageIds, type) => {
171
+ // Ahead of the empty-list exit: the types this method handles elsewhere
172
+ // resolve without sending anything, so a typo looked like a no-op.
173
+ assertArgumentDomain('sendReceipt', 'type', type, MESSAGE_RECEIPT_TYPES);
164
174
  if (!messageIds.length)
165
175
  return;
166
176
  if (type === 'read' || type === 'read-self') {
@@ -193,6 +203,7 @@ export const makeMessageMethods = (ctx) => ({
193
203
  * Send receipts for multiple message keys, grouped by JID and participant.
194
204
  */
195
205
  sendReceipts: async (keys, type) => {
206
+ assertArgumentDomain('sendReceipts', 'type', type, MESSAGE_RECEIPT_TYPES);
196
207
  const client = await ctx.getClient();
197
208
  const receiptKeys = receiptMessageKeys(keys);
198
209
  if (type === 'read' || type === 'read-self') {
@@ -224,7 +235,7 @@ export const makeMessageMethods = (ctx) => ({
224
235
  type: WAProto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
225
236
  }
226
237
  };
227
- const bytes = encodeProto('Message', message);
238
+ const bytes = encodeProtoCompat('Message', message);
228
239
  return (await ctx.getClient()).relayMessageBytes(messageKey.remoteJid, bytes, null);
229
240
  }
230
241
  });
@@ -2,6 +2,8 @@ import type { NewsletterMetadataResult } from '@oxidezap/whatsapp-rust-bridge';
2
2
  import type { NewsletterMetadata, NewsletterUpdate } from '../Types/Newsletter.js';
3
3
  import type { WAMediaUpload } from '../Types/index.js';
4
4
  import type { SocketContext } from './types.js';
5
+ export declare const NEWSLETTER_KEY_TYPES: readonly ['invite', 'jid'];
6
+ export type NewsletterKeyType = (typeof NEWSLETTER_KEY_TYPES)[number];
5
7
  export declare const makeNewsletterMethods: (ctx: SocketContext) => {
6
8
  newsletterCreate: (name: string, description?: string) => Promise<NewsletterMetadata>;
7
9
  /**
@@ -9,7 +11,7 @@ export declare const makeNewsletterMethods: (ctx: SocketContext) => {
9
11
  * rather than one that inspects the key. Resolves to null when the
10
12
  * newsletter does not exist, matching upstream.
11
13
  */
12
- newsletterMetadata: (type: 'invite' | 'jid', key: string) => Promise<NewsletterMetadata | null>;
14
+ newsletterMetadata: (type: NewsletterKeyType, key: string) => Promise<NewsletterMetadata | null>;
13
15
  /**
14
16
  * `picture` is base64 of an already-generated image, and the empty string
15
17
  * means remove, as upstream builds it. The core splits those into two
@@ -1,7 +1,9 @@
1
1
  import { Buffer } from 'node:buffer';
2
2
  import { bridgeNewsletterMetadataToBaileys } from '../Compatibility/newsletter-results.js';
3
+ import { assertArgumentDomain } from '../Utils/argument-domain.js';
3
4
  import { Boom } from '../Utils/boom.js';
4
5
  import { generateProfilePicture } from '../Utils/messages-media.js';
6
+ export const NEWSLETTER_KEY_TYPES = ['invite', 'jid'];
5
7
  export const makeNewsletterMethods = (ctx) => ({
6
8
  newsletterCreate: async (name, description) => {
7
9
  return bridgeNewsletterMetadataToBaileys(await (await ctx.getClient()).newsletterCreate(name, description ?? null));
@@ -12,9 +14,7 @@ export const makeNewsletterMethods = (ctx) => ({
12
14
  * newsletter does not exist, matching upstream.
13
15
  */
14
16
  newsletterMetadata: async (type, key) => {
15
- if (type !== 'invite' && type !== 'jid') {
16
- throw new Boom(`newsletterMetadata: unknown key type '${type}'`, { statusCode: 400 });
17
- }
17
+ assertArgumentDomain('newsletterMetadata', 'type', type, NEWSLETTER_KEY_TYPES);
18
18
  const client = await ctx.getClient();
19
19
  const result = type === 'invite' ? await client.newsletterMetadataByInvite(key) : await client.newsletterMetadata(key);
20
20
  return result ? bridgeNewsletterMetadataToBaileys(result) : null;
@@ -1,7 +1,8 @@
1
+ import { type WAChatState, type WAPresenceStatus } from '../Types/index.js';
1
2
  import type { SocketContext } from './types.js';
2
3
  export declare const makePresenceMethods: (ctx: SocketContext) => {
3
- sendPresence: (status: 'available' | 'unavailable') => Promise<void>;
4
+ sendPresence: (status: WAPresenceStatus) => Promise<void>;
4
5
  presenceSubscribe: (toJid: string) => Promise<void>;
5
- sendChatState: (jid: string, state: 'composing' | 'recording' | 'paused') => Promise<void>;
6
+ sendChatState: (jid: string, state: WAChatState) => Promise<void>;
6
7
  };
7
8
  //# sourceMappingURL=presence.d.ts.map
@@ -1,11 +1,15 @@
1
+ import { WA_CHAT_STATES, WA_PRESENCE_STATUSES } from '../Types/index.js';
2
+ import { assertArgumentDomain } from '../Utils/argument-domain.js';
1
3
  export const makePresenceMethods = (ctx) => ({
2
4
  sendPresence: async (status) => {
5
+ assertArgumentDomain('sendPresence', 'status', status, WA_PRESENCE_STATUSES);
3
6
  await (await ctx.getClient()).sendPresence(status);
4
7
  },
5
8
  presenceSubscribe: async (toJid) => {
6
9
  await (await ctx.getClient()).presenceSubscribe(toJid);
7
10
  },
8
11
  sendChatState: async (jid, state) => {
12
+ assertArgumentDomain('sendChatState', 'state', state, WA_CHAT_STATES);
9
13
  await (await ctx.getClient()).sendChatState(jid, state);
10
14
  }
11
15
  });
@@ -1,7 +1,13 @@
1
- import type { WAPrivacyCallValue, WAPrivacyGroupAddValue, WAPrivacyMessagesValue, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '../Types/index.js';
1
+ import { type WAPrivacyCallValue, type WAPrivacyGroupAddValue, type WAPrivacyMessagesValue, type WAPrivacyOnlineValue, type WAPrivacyValue, type WAReadReceiptsValue } from '../Types/index.js';
2
2
  import type { SocketContext } from './types.js';
3
3
  export declare const makePrivacyMethods: (ctx: SocketContext) => {
4
4
  fetchPrivacySettings: (force?: boolean) => Promise<any>;
5
+ /**
6
+ * The untyped escape hatch, left open on purpose: the bridge takes both
7
+ * halves as plain strings and the core's wire enums carry a fallback, so
8
+ * this is the way to reach a category or value the wrappers below do not
9
+ * name yet. The wrappers are the checked path.
10
+ */
5
11
  updatePrivacySetting: (category: string, value: string) => Promise<void>;
6
12
  updateLastSeenPrivacy: (value: WAPrivacyValue) => Promise<void>;
7
13
  updateOnlinePrivacy: (value: WAPrivacyOnlineValue) => Promise<void>;
@@ -1,3 +1,5 @@
1
+ import { WA_PRIVACY_CALL_VALUES, WA_PRIVACY_GROUP_ADD_VALUES, WA_PRIVACY_MESSAGES_VALUES, WA_PRIVACY_ONLINE_VALUES, WA_PRIVACY_VALUES, WA_READ_RECEIPTS_VALUES } from '../Types/index.js';
2
+ import { assertArgumentDomain } from '../Utils/argument-domain.js';
1
3
  export const makePrivacyMethods = (ctx) => {
2
4
  /** Per socket, so a send loop calling this does not flood the log. */
3
5
  let warnedAboutPrivacyTokens = false;
@@ -6,31 +8,45 @@ export const makePrivacyMethods = (ctx) => {
6
8
  void force;
7
9
  return (await ctx.getClient()).fetchPrivacySettings();
8
10
  },
11
+ /**
12
+ * The untyped escape hatch, left open on purpose: the bridge takes both
13
+ * halves as plain strings and the core's wire enums carry a fallback, so
14
+ * this is the way to reach a category or value the wrappers below do not
15
+ * name yet. The wrappers are the checked path.
16
+ */
9
17
  updatePrivacySetting: async (category, value) => {
10
18
  await (await ctx.getClient()).updatePrivacySetting(category, value);
11
19
  },
12
20
  updateLastSeenPrivacy: async (value) => {
21
+ assertArgumentDomain('updateLastSeenPrivacy', 'value', value, WA_PRIVACY_VALUES);
13
22
  await (await ctx.getClient()).updatePrivacySetting('last', value);
14
23
  },
15
24
  updateOnlinePrivacy: async (value) => {
25
+ assertArgumentDomain('updateOnlinePrivacy', 'value', value, WA_PRIVACY_ONLINE_VALUES);
16
26
  await (await ctx.getClient()).updatePrivacySetting('online', value);
17
27
  },
18
28
  updateProfilePicturePrivacy: async (value) => {
29
+ assertArgumentDomain('updateProfilePicturePrivacy', 'value', value, WA_PRIVACY_VALUES);
19
30
  await (await ctx.getClient()).updatePrivacySetting('profile', value);
20
31
  },
21
32
  updateStatusPrivacy: async (value) => {
33
+ assertArgumentDomain('updateStatusPrivacy', 'value', value, WA_PRIVACY_VALUES);
22
34
  await (await ctx.getClient()).updatePrivacySetting('status', value);
23
35
  },
24
36
  updateReadReceiptsPrivacy: async (value) => {
37
+ assertArgumentDomain('updateReadReceiptsPrivacy', 'value', value, WA_READ_RECEIPTS_VALUES);
25
38
  await (await ctx.getClient()).updatePrivacySetting('readreceipts', value);
26
39
  },
27
40
  updateGroupsAddPrivacy: async (value) => {
41
+ assertArgumentDomain('updateGroupsAddPrivacy', 'value', value, WA_PRIVACY_GROUP_ADD_VALUES);
28
42
  await (await ctx.getClient()).updatePrivacySetting('groupadd', value);
29
43
  },
30
44
  updateCallPrivacy: async (value) => {
45
+ assertArgumentDomain('updateCallPrivacy', 'value', value, WA_PRIVACY_CALL_VALUES);
31
46
  await (await ctx.getClient()).updatePrivacySetting('calladd', value);
32
47
  },
33
48
  updateMessagesPrivacy: async (value) => {
49
+ assertArgumentDomain('updateMessagesPrivacy', 'value', value, WA_PRIVACY_MESSAGES_VALUES);
34
50
  await (await ctx.getClient()).updatePrivacySetting('messages', value);
35
51
  },
36
52
  /**
@@ -2,6 +2,8 @@ import type { BotListInfo } from '../Types/Chat.js';
2
2
  import type { NewChatMessageCapInfo } from '../Types/State.js';
3
3
  import type { MediaConnInfo } from '../Types/Message.js';
4
4
  import type { SocketContext } from './types.js';
5
+ export declare const DIRTY_BIT_TYPES: readonly ['account_sync', 'groups'];
6
+ export type DirtyBitType = (typeof DIRTY_BIT_TYPES)[number];
5
7
  export declare const makeServerQueryMethods: (ctx: SocketContext) => {
6
8
  /**
7
9
  * `maxContentLengthBytes` is absent by design: the core's hosts carry
@@ -19,7 +21,7 @@ export declare const makeServerQueryMethods: (ctx: SocketContext) => {
19
21
  fetchNewChatMessageCap: () => Promise<NewChatMessageCapInfo & {
20
22
  remaining_quota?: number;
21
23
  }>;
22
- cleanDirtyBits: (type: 'account_sync' | 'groups', fromTimestamp?: number | string) => Promise<void>;
24
+ cleanDirtyBits: (type: DirtyBitType, fromTimestamp?: number | string) => Promise<void>;
23
25
  /**
24
26
  * Refused rather than wired up. The core already fires a peer data
25
27
  * request itself when a message fails to decrypt, with its own age
@@ -1,4 +1,6 @@
1
+ import { assertArgumentDomain } from '../Utils/argument-domain.js';
1
2
  import { Boom } from '../Utils/boom.js';
3
+ export const DIRTY_BIT_TYPES = ['account_sync', 'groups'];
2
4
  /**
3
5
  * Every section, flattened and deduplicated, rather than only the section the
4
6
  * server types `all`.
@@ -85,6 +87,7 @@ export const makeServerQueryMethods = (ctx) => {
85
87
  return toCapInfo(await (await ctx.getClient()).fetchNewChatMessageCappingInfo());
86
88
  },
87
89
  cleanDirtyBits: async (type, fromTimestamp) => {
90
+ assertArgumentDomain('cleanDirtyBits', 'type', type, DIRTY_BIT_TYPES);
88
91
  let timestamp = null;
89
92
  if (fromTimestamp !== undefined) {
90
93
  // A blank string is not a timestamp, and `Number('')` is the epoch,
@@ -1,3 +1,4 @@
1
+ import type Long from 'long';
1
2
  import type { Buffer } from 'node:buffer';
2
3
  import type { JsStoreCallbacks } from '@oxidezap/whatsapp-rust-bridge';
3
4
  import type { proto } from '../WAProto/runtime.js';
@@ -43,7 +44,9 @@ export type AccountSettings = {
43
44
  /** unarchive chats when a new message is received */
44
45
  unarchiveChats: boolean;
45
46
  /** the default mode to start new conversations with */
46
- defaultDisappearingMode?: Pick<proto.IConversation, 'ephemeralExpiration' | 'ephemeralSettingTimestamp'>;
47
+ defaultDisappearingMode?: Pick<proto.IConversation, 'ephemeralExpiration'> & {
48
+ ephemeralSettingTimestamp?: number | Long | null;
49
+ };
47
50
  };
48
51
  /**
49
52
  * Authentication credentials.
@@ -6,15 +6,33 @@ import type { LabelActionBody } from './Label.js';
6
6
  import type { ChatLabelAssociationActionBody } from './LabelAssociation.js';
7
7
  import type { MessageLabelAssociationActionBody } from './LabelAssociation.js';
8
8
  import type { MinimalMessage, WAMessageKey } from './Message.js';
9
- /** privacy settings in WhatsApp Web */
10
- export type WAPrivacyValue = 'all' | 'contacts' | 'contact_blacklist' | 'none';
11
- export type WAPrivacyOnlineValue = 'all' | 'match_last_seen';
12
- export type WAPrivacyGroupAddValue = 'all' | 'contacts' | 'contact_blacklist';
13
- export type WAReadReceiptsValue = 'all' | 'none';
14
- export type WAPrivacyCallValue = 'all' | 'known';
15
- export type WAPrivacyMessagesValue = 'all' | 'contacts';
9
+ /**
10
+ * privacy settings in WhatsApp Web
11
+ *
12
+ * Each of these is a set first and a type second: the wrappers that take one
13
+ * check the value against the same array the type is derived from, so a value
14
+ * cannot be accepted by the compiler and refused at runtime, or the reverse.
15
+ */
16
+ export declare const WA_PRIVACY_VALUES: readonly ['all', 'contacts', 'contact_blacklist', 'none'];
17
+ export type WAPrivacyValue = (typeof WA_PRIVACY_VALUES)[number];
18
+ export declare const WA_PRIVACY_ONLINE_VALUES: readonly ['all', 'match_last_seen'];
19
+ export type WAPrivacyOnlineValue = (typeof WA_PRIVACY_ONLINE_VALUES)[number];
20
+ export declare const WA_PRIVACY_GROUP_ADD_VALUES: readonly ['all', 'contacts', 'contact_blacklist'];
21
+ export type WAPrivacyGroupAddValue = (typeof WA_PRIVACY_GROUP_ADD_VALUES)[number];
22
+ export declare const WA_READ_RECEIPTS_VALUES: readonly ['all', 'none'];
23
+ export type WAReadReceiptsValue = (typeof WA_READ_RECEIPTS_VALUES)[number];
24
+ export declare const WA_PRIVACY_CALL_VALUES: readonly ['all', 'known'];
25
+ export type WAPrivacyCallValue = (typeof WA_PRIVACY_CALL_VALUES)[number];
26
+ export declare const WA_PRIVACY_MESSAGES_VALUES: readonly ['all', 'contacts'];
27
+ export type WAPrivacyMessagesValue = (typeof WA_PRIVACY_MESSAGES_VALUES)[number];
28
+ /** the two the account itself broadcasts, as opposed to the per-chat states */
29
+ export declare const WA_PRESENCE_STATUSES: readonly ['unavailable', 'available'];
30
+ export type WAPresenceStatus = (typeof WA_PRESENCE_STATUSES)[number];
31
+ export declare const WA_CHAT_STATES: readonly ['composing', 'recording', 'paused'];
32
+ export type WAChatState = (typeof WA_CHAT_STATES)[number];
16
33
  /** set of statuses visible to other people; see updatePresence() in WhatsAppWeb.Send */
17
- export type WAPresence = 'unavailable' | 'available' | 'composing' | 'recording' | 'paused';
34
+ export declare const WA_PRESENCES: readonly ["unavailable", "available", "composing", "recording", "paused"];
35
+ export type WAPresence = (typeof WA_PRESENCES)[number];
18
36
  export declare const ALL_WA_PATCH_NAMES: readonly ['critical_block', 'critical_unblock_low', 'regular_high', 'regular_low', 'regular'];
19
37
  export type WAPatchName = (typeof ALL_WA_PATCH_NAMES)[number];
20
38
  export interface PresenceData {