@oxidezap/baileyrs 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -0
- package/lib/Compatibility/legacy-store/namespaces.d.ts +20 -0
- package/lib/Compatibility/legacy-store/namespaces.js +27 -0
- package/lib/Compatibility/newsletter-results.d.ts +15 -0
- package/lib/Compatibility/newsletter-results.js +38 -0
- package/lib/Socket/business.d.ts +29 -0
- package/lib/Socket/business.js +104 -0
- package/lib/Socket/chat-actions.d.ts +20 -11
- package/lib/Socket/chat-actions.js +171 -83
- package/lib/Socket/events.js +5 -5
- package/lib/Socket/index.d.ts +85 -14
- package/lib/Socket/index.js +36 -26
- package/lib/Socket/internals.d.ts +88 -0
- package/lib/Socket/internals.js +145 -0
- package/lib/Socket/messages.d.ts +1 -15
- package/lib/Socket/messages.js +3 -22
- package/lib/Socket/newsletter.d.ts +61 -6
- package/lib/Socket/newsletter.js +125 -7
- package/lib/Socket/privacy.d.ts +25 -0
- package/lib/Socket/privacy.js +54 -0
- package/lib/Socket/server-queries.d.ts +38 -0
- package/lib/Socket/server-queries.js +121 -0
- package/lib/Socket/types.d.ts +6 -0
- package/lib/Types/Product.d.ts +9 -0
- package/lib/Utils/index.d.ts +1 -0
- package/lib/Utils/index.js +3 -0
- package/lib/Utils/link-preview.d.ts +60 -0
- package/lib/Utils/link-preview.js +357 -0
- package/lib/Utils/messages.d.ts +20 -7
- package/lib/Utils/messages.js +14 -3
- package/lib/Utils/wrap-legacy-store.d.ts +1 -0
- package/lib/Utils/wrap-legacy-store.js +1 -0
- package/package.json +4 -2
package/lib/Socket/events.js
CHANGED
|
@@ -813,7 +813,7 @@ const dispatchCanonicalEvent = (canonical, dispatchCtx) => {
|
|
|
813
813
|
}
|
|
814
814
|
catch (err) {
|
|
815
815
|
// One bad event must not poison the rest of the pipeline.
|
|
816
|
-
dispatchCtx.ctx.
|
|
816
|
+
dispatchCtx.ctx.reportUnexpectedError(err, `dispatching a '${canonical.type}' event`);
|
|
817
817
|
}
|
|
818
818
|
};
|
|
819
819
|
/** Aggregate adjacent ordinary messages while preserving every side-effecting
|
|
@@ -852,7 +852,7 @@ const dispatchCanonicalBatch = (ctx, dispatchCtx, count, canonicalAt) => {
|
|
|
852
852
|
}
|
|
853
853
|
}
|
|
854
854
|
catch (err) {
|
|
855
|
-
ctx.
|
|
855
|
+
ctx.reportUnexpectedError(err, `dispatching a '${CANONICAL_MESSAGE_EVENT}' event`);
|
|
856
856
|
}
|
|
857
857
|
}
|
|
858
858
|
if (pending)
|
|
@@ -884,7 +884,7 @@ export const makeEventHandlers = (ctx, callbacks) => {
|
|
|
884
884
|
view = decodeMessageWireBatch(batch);
|
|
885
885
|
}
|
|
886
886
|
catch (err) {
|
|
887
|
-
ctx.
|
|
887
|
+
ctx.reportUnexpectedError(err, 'decoding the message wire batch');
|
|
888
888
|
return;
|
|
889
889
|
}
|
|
890
890
|
const { messageData, messageOffsets, infos } = view;
|
|
@@ -923,7 +923,7 @@ export const makeEventHandlers = (ctx, callbacks) => {
|
|
|
923
923
|
receipts = decodeReceiptWireBatch(batch);
|
|
924
924
|
}
|
|
925
925
|
catch (err) {
|
|
926
|
-
ctx.
|
|
926
|
+
ctx.reportUnexpectedError(err, 'decoding the receipt wire batch');
|
|
927
927
|
return;
|
|
928
928
|
}
|
|
929
929
|
// The decoded payload matches the single-event wire shape; the union's
|
|
@@ -937,7 +937,7 @@ export const makeEventHandlers = (ctx, callbacks) => {
|
|
|
937
937
|
acks = decodeServerAckWireBatch(batch);
|
|
938
938
|
}
|
|
939
939
|
catch (err) {
|
|
940
|
-
ctx.
|
|
940
|
+
ctx.reportUnexpectedError(err, 'decoding the server-ack wire batch');
|
|
941
941
|
return;
|
|
942
942
|
}
|
|
943
943
|
for (const data of acks)
|
package/lib/Socket/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ 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,
|
|
5
|
+
import type { BinaryNode, AuthenticationCreds, ConnectionState, Contact, ReachoutTimelockState, SignalKeyStoreWithTransaction, UserFacingSocketConfig, WABusinessProfile, WAMessage, WAMessageKey } from '../Types/index.js';
|
|
6
6
|
import type Long from 'long';
|
|
7
7
|
import type { MediaDownloadOptions } from '../Utils/messages-media.js';
|
|
8
8
|
import type { proto } from '../WAProto/runtime.js';
|
|
@@ -12,12 +12,33 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
12
12
|
sendRetryRequest: (node: BinaryNode, forceIncludeKeys?: boolean) => Promise<void>;
|
|
13
13
|
updateBlockStatus: (jid: string, action: 'block' | 'unblock') => Promise<void>;
|
|
14
14
|
fetchBlocklist: () => Promise<Array<string | undefined>>;
|
|
15
|
+
getCatalog: ({ jid, limit, cursor }: import("../index.js").GetCatalogOptions) => Promise<import("../index.js").CatalogPage>;
|
|
16
|
+
getCollections: (jid?: string, limit?: number) => Promise<import("../index.js").CollectionsPage>;
|
|
17
|
+
getOrderDetails: (orderId: string, tokenBase64: string, sellerJid?: string) => Promise<import("@oxidezap/whatsapp-rust-bridge").OrderResult>;
|
|
18
|
+
updateBussinesProfile: (args: import("../Types/Bussines.js").UpdateBussinesProfileProps) => Promise<void>;
|
|
19
|
+
updateCoverPhoto: (photo: import("../index.js").WAMediaUpload) => Promise<never>;
|
|
20
|
+
removeCoverPhoto: (id: string) => Promise<void>;
|
|
21
|
+
productCreate: (create: import("../index.js").ProductCreate) => Promise<never>;
|
|
22
|
+
productUpdate: (productId: string, update: import("../index.js").ProductUpdate) => Promise<never>;
|
|
23
|
+
productDelete: (productIds: string[]) => Promise<never>;
|
|
15
24
|
pinChat: (jid: string, pin: boolean) => Promise<void>;
|
|
16
25
|
muteChat: (jid: string, muteUntil?: number | null) => Promise<void>;
|
|
17
26
|
archiveChat: (jid: string, archive: boolean) => Promise<void>;
|
|
18
27
|
starMessage: (jid: string, messageId: string, star: boolean) => Promise<void>;
|
|
19
28
|
chatModify: (mod: import("../index.js").ChatModification, jid: string) => Promise<void>;
|
|
20
|
-
|
|
29
|
+
addOrEditContact: (jid: string, contact: proto.SyncActionValue.IContactAction) => Promise<void>;
|
|
30
|
+
removeContact: (jid: string) => Promise<void>;
|
|
31
|
+
addLabel: (jid: string, labels: import("../Types/Label.js").LabelActionBody) => Promise<void>;
|
|
32
|
+
addChatLabel: (jid: string, labelId: string) => Promise<void>;
|
|
33
|
+
removeChatLabel: (jid: string, labelId: string) => Promise<void>;
|
|
34
|
+
addMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
35
|
+
removeMessageLabel: (jid: string, messageId: string, labelId: string) => Promise<void>;
|
|
36
|
+
star: (jid: string, messages: {
|
|
37
|
+
id: string;
|
|
38
|
+
fromMe?: boolean;
|
|
39
|
+
}[], star: boolean) => Promise<void>;
|
|
40
|
+
addOrEditQuickReply: (quickReply: import("../Types/Bussines.js").QuickReplyAction) => Promise<void>;
|
|
41
|
+
removeQuickReply: (timestamp: string) => Promise<void>;
|
|
21
42
|
onWhatsApp: (...phoneNumber: string[]) => Promise<import("./contacts.js").OnWhatsAppResult[] | undefined>;
|
|
22
43
|
profilePictureUrl: (jid: string, type?: 'preview' | 'image', timeoutMs?: number) => Promise<string | undefined>;
|
|
23
44
|
fetchUserInfo: (...jids: string[]) => Promise<Record<string, import("@oxidezap/whatsapp-rust-bridge").UserInfoResult>>;
|
|
@@ -74,6 +95,14 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
74
95
|
communityMemberAddMode: (jid: string, mode: 'admin_add' | 'all_member_add') => Promise<void>;
|
|
75
96
|
communityJoinApprovalMode: (jid: string, mode: 'on' | 'off') => Promise<void>;
|
|
76
97
|
communityFetchAllParticipating: () => Promise<Record<string, import("../index.js").GroupMetadata>>;
|
|
98
|
+
waitForSocketOpen: () => Promise<void>;
|
|
99
|
+
upsertMessage: (msg: WAMessage, type: import("../index.js").MessageUpsertType) => Promise<void>;
|
|
100
|
+
onUnexpectedError: (err: Error, msg: string) => void;
|
|
101
|
+
resyncAppState: (collections?: readonly ('critical_block' | 'critical_unblock_low' | 'regular_high' | 'regular_low' | 'regular')[], isInitialSync?: boolean) => Promise<void>;
|
|
102
|
+
updateServerTimeOffset: (node: BinaryNode) => never;
|
|
103
|
+
sendUnifiedSession: () => Promise<never>;
|
|
104
|
+
appPatch: (patchCreate: import("../index.js").WAPatchCreate) => Promise<never>;
|
|
105
|
+
messageRetryManager: null;
|
|
77
106
|
sendMessage: (jid: string, content: import("../index.js").AnyMessageContent, options?: Omit<import("../index.js").MessageGenerationOptions, 'waClient' | 'logger' | 'userJid' | 'mediaInNote'>) => Promise<WAMessage>;
|
|
78
107
|
updateMediaMessage: (message: WAMessage) => Promise<WAMessage>;
|
|
79
108
|
relayMessage: (jid: string, message: proto.IMessage, options: import("../index.js").MessageRelayOptions) => Promise<string>;
|
|
@@ -81,12 +110,31 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
81
110
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: import("../index.js").MessageReceiptType) => Promise<void>;
|
|
82
111
|
sendReceipts: (keys: WAMessageKey[], type: import("../index.js").MessageReceiptType) => Promise<void>;
|
|
83
112
|
requestPlaceholderResend: (messageKey: WAMessageKey, msgData?: Partial<WAMessage>) => Promise<string | undefined>;
|
|
84
|
-
newsletterCreate: (name: string, description?: string) => Promise<import("
|
|
85
|
-
newsletterMetadata: (jid: string) => Promise<import("
|
|
113
|
+
newsletterCreate: (name: string, description?: string) => Promise<import("../index.js").NewsletterMetadata>;
|
|
114
|
+
newsletterMetadata: (type: 'invite' | 'jid', key: string) => Promise<import("../index.js").NewsletterMetadata | null>;
|
|
115
|
+
newsletterUpdate: (jid: string, updates: import("../index.js").NewsletterUpdate) => Promise<import("../index.js").NewsletterMetadata>;
|
|
116
|
+
newsletterUpdateName: (jid: string, name: string) => Promise<import("../index.js").NewsletterMetadata>;
|
|
117
|
+
newsletterUpdateDescription: (jid: string, description: string) => Promise<import("../index.js").NewsletterMetadata>;
|
|
118
|
+
newsletterUpdatePicture: (jid: string, content: import("../index.js").WAMediaUpload) => Promise<import("../index.js").NewsletterMetadata>;
|
|
119
|
+
newsletterRemovePicture: (jid: string) => Promise<import("../index.js").NewsletterMetadata>;
|
|
120
|
+
newsletterFollow: (jid: string) => Promise<import("../index.js").NewsletterMetadata>;
|
|
121
|
+
newsletterUnfollow: (jid: string) => Promise<void>;
|
|
86
122
|
newsletterSubscribe: (jid: string) => Promise<import("@oxidezap/whatsapp-rust-bridge").NewsletterMetadataResult>;
|
|
87
123
|
newsletterUnsubscribe: (jid: string) => Promise<void>;
|
|
124
|
+
newsletterMute: (jid: string) => Promise<void>;
|
|
125
|
+
newsletterUnmute: (jid: string) => Promise<void>;
|
|
126
|
+
newsletterSubscribers: (jid: string) => Promise<{
|
|
127
|
+
subscribers: number;
|
|
128
|
+
}>;
|
|
88
129
|
newsletterReactMessage: (jid: string, serverId: string, reaction?: string) => Promise<void>;
|
|
89
|
-
|
|
130
|
+
newsletterFetchMessages: (jid: string, count: number, since?: number, after?: number) => Promise<import("@oxidezap/whatsapp-rust-bridge").NewsletterMessageResult[]>;
|
|
131
|
+
subscribeNewsletterUpdates: (jid: string) => Promise<{
|
|
132
|
+
duration: string;
|
|
133
|
+
}>;
|
|
134
|
+
newsletterAdminCount: (jid: string) => Promise<number>;
|
|
135
|
+
newsletterChangeOwner: (jid: string, newOwnerJid: string) => Promise<void>;
|
|
136
|
+
newsletterDemote: (jid: string, userJid: string) => Promise<void>;
|
|
137
|
+
newsletterDelete: (jid: string) => Promise<void>;
|
|
90
138
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
91
139
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
92
140
|
digestKeyBundle: () => Promise<void>;
|
|
@@ -94,6 +142,30 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
94
142
|
sendPresence: (status: 'available' | 'unavailable') => Promise<void>;
|
|
95
143
|
presenceSubscribe: (toJid: string) => Promise<void>;
|
|
96
144
|
sendChatState: (jid: string, state: 'composing' | 'recording' | 'paused') => Promise<void>;
|
|
145
|
+
fetchPrivacySettings: (force?: boolean) => Promise<any>;
|
|
146
|
+
updatePrivacySetting: (category: string, value: string) => Promise<void>;
|
|
147
|
+
updateLastSeenPrivacy: (value: import("../index.js").WAPrivacyValue) => Promise<void>;
|
|
148
|
+
updateOnlinePrivacy: (value: import("../index.js").WAPrivacyOnlineValue) => Promise<void>;
|
|
149
|
+
updateProfilePicturePrivacy: (value: import("../index.js").WAPrivacyValue) => Promise<void>;
|
|
150
|
+
updateStatusPrivacy: (value: import("../index.js").WAPrivacyValue) => Promise<void>;
|
|
151
|
+
updateReadReceiptsPrivacy: (value: import("../index.js").WAReadReceiptsValue) => Promise<void>;
|
|
152
|
+
updateGroupsAddPrivacy: (value: import("../index.js").WAPrivacyGroupAddValue) => Promise<void>;
|
|
153
|
+
updateCallPrivacy: (value: import("../index.js").WAPrivacyCallValue) => Promise<void>;
|
|
154
|
+
updateMessagesPrivacy: (value: import("../index.js").WAPrivacyMessagesValue) => Promise<void>;
|
|
155
|
+
issuePrivacyTokens: (jids: string[], timestamp?: number) => Promise<void>;
|
|
156
|
+
refreshMediaConn: (forceGet?: boolean) => Promise<Omit<import("../index.js").MediaConnInfo, 'hosts'> & {
|
|
157
|
+
hosts: {
|
|
158
|
+
hostname: string;
|
|
159
|
+
}[];
|
|
160
|
+
}>;
|
|
161
|
+
getMediaHost: () => string;
|
|
162
|
+
getBotListV2: () => Promise<import("../index.js").BotListInfo[]>;
|
|
163
|
+
fetchNewChatMessageCap: () => Promise<import("../index.js").NewChatMessageCapInfo & {
|
|
164
|
+
remaining_quota?: number;
|
|
165
|
+
}>;
|
|
166
|
+
cleanDirtyBits: (type: 'account_sync' | 'groups', fromTimestamp?: number | string) => Promise<void>;
|
|
167
|
+
sendPeerDataOperationMessage: (_pdoMessage: unknown) => Promise<never>;
|
|
168
|
+
createCallLink: (_type: 'audio' | 'video', _event?: unknown, _timeoutMs?: number) => Promise<never>;
|
|
97
169
|
requestPairingCode: (phoneNumber: string, customPairingCode?: string) => Promise<string>;
|
|
98
170
|
setPushName: (name: string) => Promise<void>;
|
|
99
171
|
updateProfileName: (name: string) => Promise<void>;
|
|
@@ -176,7 +248,14 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
176
248
|
waitForMessage: <T>(msgId: string, timeoutMs?: number | undefined) => Promise<T | undefined>;
|
|
177
249
|
query: (node: BinaryNode, timeoutMs?: number) => Promise<BinaryNode>;
|
|
178
250
|
sendRawMessage: (data: Uint8Array | Buffer) => Promise<void>;
|
|
179
|
-
|
|
251
|
+
/**
|
|
252
|
+
* `dsmMessage` is accepted so the signature matches upstream, and
|
|
253
|
+
* refused rather than ignored. Upstream uses it to encrypt a different
|
|
254
|
+
* plaintext for the caller's own other devices; the engine encrypts one
|
|
255
|
+
* payload for every recipient, so honouring it is not possible here and
|
|
256
|
+
* dropping it would send those devices the wrong message.
|
|
257
|
+
*/
|
|
258
|
+
createParticipantNodes: (jids: string[], message: proto.IMessage, extraAttrs?: BinaryNode['attrs'], dsmMessage?: proto.IMessage) => Promise<{
|
|
180
259
|
nodes: BinaryNode[];
|
|
181
260
|
shouldIncludeDeviceIdentity: boolean;
|
|
182
261
|
}>;
|
|
@@ -203,14 +282,6 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
203
282
|
waUploadToServer: (data: Uint8Array | Buffer, opts: {
|
|
204
283
|
mediaType: MediaType;
|
|
205
284
|
}) => Promise<UploadMediaResult>;
|
|
206
|
-
fetchPrivacySettings: (force?: boolean) => Promise<any>;
|
|
207
|
-
updatePrivacySetting: (category: string, value: string) => Promise<void>;
|
|
208
|
-
updateLastSeenPrivacy: (value: WAPrivacyValue) => Promise<void>;
|
|
209
|
-
updateOnlinePrivacy: (value: WAPrivacyOnlineValue) => Promise<void>;
|
|
210
|
-
updateProfilePicturePrivacy: (value: WAPrivacyValue) => Promise<void>;
|
|
211
|
-
updateStatusPrivacy: (value: WAPrivacyValue) => Promise<void>;
|
|
212
|
-
updateReadReceiptsPrivacy: (value: WAReadReceiptsValue) => Promise<void>;
|
|
213
|
-
updateGroupsAddPrivacy: (value: WAPrivacyGroupAddValue) => Promise<void>;
|
|
214
285
|
updateDefaultDisappearingMode: (duration: number) => Promise<void>;
|
|
215
286
|
rejectCall: (callId: string, callFrom: string) => Promise<void>;
|
|
216
287
|
/**
|
package/lib/Socket/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { makeNativeCryptoProvider } from '../Utils/native-crypto-provider.js';
|
|
|
21
21
|
import { wrapLegacyStore } from '../Utils/wrap-legacy-store.js';
|
|
22
22
|
import { assertNodeErrorFree } from '../WABinary/generic-utils.js';
|
|
23
23
|
import { makeBlockingMethods } from './blocking.js';
|
|
24
|
+
import { makeBusinessMethods } from './business.js';
|
|
24
25
|
import { makeChatActionMethods } from './chat-actions.js';
|
|
25
26
|
import { makeContactMethods } from './contacts.js';
|
|
26
27
|
import { makeCommunityMethods } from './communities.js';
|
|
@@ -28,10 +29,13 @@ import { makeBridgeClientOwner } from './bridge-client-owner.js';
|
|
|
28
29
|
import { makeTerminalCloseReporter } from './terminal-close-reporter.js';
|
|
29
30
|
import { makeEventHandlers } from './events.js';
|
|
30
31
|
import { makeGroupMethods } from './groups.js';
|
|
32
|
+
import { makeInternalMethods, makeUnexpectedErrorReporter } from './internals.js';
|
|
31
33
|
import { makeMessageMethods } from './messages.js';
|
|
32
34
|
import { makeNewsletterMethods } from './newsletter.js';
|
|
33
35
|
import { makePreKeyMethods } from './prekeys.js';
|
|
34
36
|
import { makePresenceMethods } from './presence.js';
|
|
37
|
+
import { makePrivacyMethods } from './privacy.js';
|
|
38
|
+
import { makeServerQueryMethods } from './server-queries.js';
|
|
35
39
|
import { makeProfileMethods } from './profile.js';
|
|
36
40
|
import { mapReachoutTimelock } from './reachout.js';
|
|
37
41
|
import { makeHttpClient, makeTransport } from './transport.js';
|
|
@@ -249,11 +253,18 @@ const makeWASocket = (config) => {
|
|
|
249
253
|
let autoReconnectEnabled = true;
|
|
250
254
|
/** Owns reporting the terminal close: once, after teardown, never not at all. */
|
|
251
255
|
const terminalClose = makeTerminalCloseReporter({ logger });
|
|
256
|
+
/**
|
|
257
|
+
* Held in a reporter rather than captured, because `sock.onUnexpectedError`
|
|
258
|
+
* is an assignable property: a consumer that replaces it has to be the one
|
|
259
|
+
* the socket's own failure paths reach afterwards.
|
|
260
|
+
*/
|
|
261
|
+
const unexpectedErrors = makeUnexpectedErrorReporter(logger);
|
|
252
262
|
const ctx = {
|
|
253
263
|
ev,
|
|
254
264
|
logger,
|
|
255
265
|
fullConfig,
|
|
256
266
|
ws,
|
|
267
|
+
reportUnexpectedError: unexpectedErrors.report,
|
|
257
268
|
getUser: () => user,
|
|
258
269
|
getMe: () => {
|
|
259
270
|
const me = auth.creds.me;
|
|
@@ -783,7 +794,17 @@ const makeWASocket = (config) => {
|
|
|
783
794
|
sendRawMessage: async (data) => {
|
|
784
795
|
return (await ctx.getClient()).sendRawMessage(data instanceof Uint8Array ? data : new Uint8Array(data));
|
|
785
796
|
},
|
|
786
|
-
|
|
797
|
+
/**
|
|
798
|
+
* `dsmMessage` is accepted so the signature matches upstream, and
|
|
799
|
+
* refused rather than ignored. Upstream uses it to encrypt a different
|
|
800
|
+
* plaintext for the caller's own other devices; the engine encrypts one
|
|
801
|
+
* payload for every recipient, so honouring it is not possible here and
|
|
802
|
+
* dropping it would send those devices the wrong message.
|
|
803
|
+
*/
|
|
804
|
+
createParticipantNodes: async (jids, message, extraAttrs, dsmMessage) => {
|
|
805
|
+
if (dsmMessage) {
|
|
806
|
+
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
|
+
}
|
|
787
808
|
const bytes = encodeProto('Message', message);
|
|
788
809
|
return (await ctx.getClient()).createParticipantNodesBytes(jids, bytes, extraAttrs ?? {});
|
|
789
810
|
},
|
|
@@ -826,31 +847,7 @@ const makeWASocket = (config) => {
|
|
|
826
847
|
const bytes = data instanceof Uint8Array && !Buffer.isBuffer(data) ? data : new Uint8Array(data);
|
|
827
848
|
return (await ctx.getClient()).uploadMedia(bytes, toBridgeMediaType(opts.mediaType));
|
|
828
849
|
},
|
|
829
|
-
|
|
830
|
-
void force;
|
|
831
|
-
return (await ctx.getClient()).fetchPrivacySettings();
|
|
832
|
-
},
|
|
833
|
-
updatePrivacySetting: async (category, value) => {
|
|
834
|
-
await (await ctx.getClient()).updatePrivacySetting(category, value);
|
|
835
|
-
},
|
|
836
|
-
updateLastSeenPrivacy: async (value) => {
|
|
837
|
-
await (await ctx.getClient()).updatePrivacySetting('last', value);
|
|
838
|
-
},
|
|
839
|
-
updateOnlinePrivacy: async (value) => {
|
|
840
|
-
await (await ctx.getClient()).updatePrivacySetting('online', value);
|
|
841
|
-
},
|
|
842
|
-
updateProfilePicturePrivacy: async (value) => {
|
|
843
|
-
await (await ctx.getClient()).updatePrivacySetting('profile', value);
|
|
844
|
-
},
|
|
845
|
-
updateStatusPrivacy: async (value) => {
|
|
846
|
-
await (await ctx.getClient()).updatePrivacySetting('status', value);
|
|
847
|
-
},
|
|
848
|
-
updateReadReceiptsPrivacy: async (value) => {
|
|
849
|
-
await (await ctx.getClient()).updatePrivacySetting('readreceipts', value);
|
|
850
|
-
},
|
|
851
|
-
updateGroupsAddPrivacy: async (value) => {
|
|
852
|
-
await (await ctx.getClient()).updatePrivacySetting('groupadd', value);
|
|
853
|
-
},
|
|
850
|
+
...makePrivacyMethods(ctx),
|
|
854
851
|
updateDefaultDisappearingMode: async (duration) => {
|
|
855
852
|
await (await ctx.getClient()).updateDefaultDisappearingMode(duration);
|
|
856
853
|
},
|
|
@@ -891,11 +888,14 @@ const makeWASocket = (config) => {
|
|
|
891
888
|
...makeContactMethods(ctx),
|
|
892
889
|
...makeProfileMethods(ctx),
|
|
893
890
|
...makeChatActionMethods(ctx),
|
|
891
|
+
...makeInternalMethods(ctx),
|
|
894
892
|
...usyncMethods,
|
|
895
893
|
...makeStanzaResponseMethods(ctx),
|
|
896
894
|
...makePresenceMethods(ctx),
|
|
897
895
|
...makeBlockingMethods(ctx),
|
|
898
896
|
...makeNewsletterMethods(ctx),
|
|
897
|
+
...makeBusinessMethods(ctx),
|
|
898
|
+
...makeServerQueryMethods(ctx),
|
|
899
899
|
downloadMedia: async (message, type, options = {}) => {
|
|
900
900
|
return downloadMediaMessage(message, type, options, {
|
|
901
901
|
logger,
|
|
@@ -904,6 +904,16 @@ const makeWASocket = (config) => {
|
|
|
904
904
|
});
|
|
905
905
|
}
|
|
906
906
|
};
|
|
907
|
+
// Assigning replaces the handler the socket itself reports through, rather
|
|
908
|
+
// than shadowing it with a second one only a consumer could reach.
|
|
909
|
+
Object.defineProperty(sock, 'onUnexpectedError', {
|
|
910
|
+
get: () => unexpectedErrors.handler,
|
|
911
|
+
set: (handler) => {
|
|
912
|
+
unexpectedErrors.handler = handler;
|
|
913
|
+
},
|
|
914
|
+
enumerable: true,
|
|
915
|
+
configurable: true
|
|
916
|
+
});
|
|
907
917
|
return sock;
|
|
908
918
|
};
|
|
909
919
|
export default makeWASocket;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { BinaryNode, MessageUpsertType, WAMessage, WAPatchCreate } from '../Types/index.js';
|
|
2
|
+
import type { ILogger } from '../Utils/logger.js';
|
|
3
|
+
import type { SocketContext } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The one place an unexpected failure is reported, shared by the socket's
|
|
6
|
+
* `onUnexpectedError` property and by the internal paths that raise them.
|
|
7
|
+
*
|
|
8
|
+
* `report` cannot throw. Some of its callers are bridge callbacks that borrow
|
|
9
|
+
* memory and are contractually forbidden from raising, so a consumer whose
|
|
10
|
+
* handler throws would cost the session its borrowed batches. A handler that
|
|
11
|
+
* fails is reported through the logger and the caller carries on.
|
|
12
|
+
*
|
|
13
|
+
* The return type says `void`, which an `async` handler also satisfies, so a
|
|
14
|
+
* handler that rejects rather than throws is contained the same way. Left
|
|
15
|
+
* loose it would surface as an unhandled rejection, which ends the process
|
|
16
|
+
* under `--unhandled-rejections=strict`.
|
|
17
|
+
*/
|
|
18
|
+
export declare const makeUnexpectedErrorReporter: (logger: ILogger) => {
|
|
19
|
+
report: (err: unknown, msg: string) => void;
|
|
20
|
+
handler: (err: unknown, msg: string) => void;
|
|
21
|
+
};
|
|
22
|
+
export declare const makeInternalMethods: (ctx: SocketContext) => {
|
|
23
|
+
/**
|
|
24
|
+
* `waitForSocket`, not `waitForConnected`: upstream waits for the socket
|
|
25
|
+
* to open, which is not the same as being logged in, and the bridge
|
|
26
|
+
* separates the two.
|
|
27
|
+
*
|
|
28
|
+
* A rejection means the socket did not open within one connect attempt,
|
|
29
|
+
* not that it never will: the engine reconnects on its own, and a caller
|
|
30
|
+
* that wants the next attempt waits again.
|
|
31
|
+
*/
|
|
32
|
+
waitForSocketOpen: () => Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Publishes a message onto the event bus, which is this layer's own job.
|
|
35
|
+
* Buffered as upstream buffers it, so a replay of many messages
|
|
36
|
+
* consolidates into the batches a listener expects rather than one
|
|
37
|
+
* event per call.
|
|
38
|
+
*
|
|
39
|
+
* The push-name half of upstream's version is not reproduced: contact
|
|
40
|
+
* state belongs to the core, and writing it from here would make two
|
|
41
|
+
* writers for one value.
|
|
42
|
+
*/
|
|
43
|
+
upsertMessage: (msg: WAMessage, type: MessageUpsertType) => Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* The same reporter the socket's own failure paths use, rather than a
|
|
46
|
+
* second one that only a consumer could reach: a dispatcher that threw
|
|
47
|
+
* or a wire batch that would not decode arrives here. The socket
|
|
48
|
+
* redefines this as an accessor, so assigning to it replaces the
|
|
49
|
+
* handler those paths report through.
|
|
50
|
+
*/
|
|
51
|
+
onUnexpectedError: (err: Error, msg: string) => void;
|
|
52
|
+
/**
|
|
53
|
+
* Resolves without forcing anything, and says so once.
|
|
54
|
+
*
|
|
55
|
+
* The engine syncs app state on connect and re-syncs every collection
|
|
56
|
+
* when the server raises the `syncd_app_state` dirty bit, so the state a
|
|
57
|
+
* caller wants current already is. There is no on-demand resync to
|
|
58
|
+
* delegate to, and rejecting would break a call whose intent is met.
|
|
59
|
+
*/
|
|
60
|
+
resyncAppState: (collections?: readonly ('critical_block' | 'critical_unblock_low' | 'regular_high' | 'regular_low' | 'regular')[], isInitialSync?: boolean) => Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Refused: the offset is protocol state the core keeps from the stanzas
|
|
63
|
+
* it already reads. A second clock here would drift from the one that
|
|
64
|
+
* actually timestamps outgoing messages.
|
|
65
|
+
*/
|
|
66
|
+
updateServerTimeOffset: (node: BinaryNode) => never;
|
|
67
|
+
/**
|
|
68
|
+
* Refused one layer down. The core's session instance is `pub(crate)`,
|
|
69
|
+
* and what exists returns a half-built stanza plus a sequence number, so
|
|
70
|
+
* exposing it would hand JavaScript the job of finishing and sequencing
|
|
71
|
+
* a lifecycle stanza.
|
|
72
|
+
*/
|
|
73
|
+
sendUnifiedSession: () => Promise<never>;
|
|
74
|
+
/**
|
|
75
|
+
* Refused: the bridge exposes app-state actions typed per action and
|
|
76
|
+
* deliberately no generic. Accepting a raw patch here would mean
|
|
77
|
+
* building mutation indices and schema versions in TypeScript, beside
|
|
78
|
+
* the copy the core already maintains.
|
|
79
|
+
*/
|
|
80
|
+
appPatch: (patchCreate: WAPatchCreate) => Promise<never>;
|
|
81
|
+
/**
|
|
82
|
+
* Null rather than absent, and rather than a shadow. Retry is the
|
|
83
|
+
* engine's, so there is no manager here to hand out, and saying so in
|
|
84
|
+
* the type is more useful than leaving the field missing.
|
|
85
|
+
*/
|
|
86
|
+
messageRetryManager: null;
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=internals.d.ts.map
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Boom } from '../Utils/boom.js';
|
|
2
|
+
/**
|
|
3
|
+
* The one place an unexpected failure is reported, shared by the socket's
|
|
4
|
+
* `onUnexpectedError` property and by the internal paths that raise them.
|
|
5
|
+
*
|
|
6
|
+
* `report` cannot throw. Some of its callers are bridge callbacks that borrow
|
|
7
|
+
* memory and are contractually forbidden from raising, so a consumer whose
|
|
8
|
+
* handler throws would cost the session its borrowed batches. A handler that
|
|
9
|
+
* fails is reported through the logger and the caller carries on.
|
|
10
|
+
*
|
|
11
|
+
* The return type says `void`, which an `async` handler also satisfies, so a
|
|
12
|
+
* handler that rejects rather than throws is contained the same way. Left
|
|
13
|
+
* loose it would surface as an unhandled rejection, which ends the process
|
|
14
|
+
* under `--unhandled-rejections=strict`.
|
|
15
|
+
*/
|
|
16
|
+
export const makeUnexpectedErrorReporter = (logger) => {
|
|
17
|
+
const logUnexpected = (err, msg) => logger.error({ err }, `unexpected error in '${msg}'`);
|
|
18
|
+
const logHandlerFailure = (err, msg, reportingError) => {
|
|
19
|
+
logger.error({ err: reportingError }, 'the onUnexpectedError handler threw');
|
|
20
|
+
logUnexpected(err, msg);
|
|
21
|
+
};
|
|
22
|
+
let handler = logUnexpected;
|
|
23
|
+
return {
|
|
24
|
+
report: (err, msg) => {
|
|
25
|
+
try {
|
|
26
|
+
const settled = handler(err, msg);
|
|
27
|
+
if (settled instanceof Promise) {
|
|
28
|
+
settled.catch(reportingError => logHandlerFailure(err, msg, reportingError));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (reportingError) {
|
|
32
|
+
logHandlerFailure(err, msg, reportingError);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
get handler() {
|
|
36
|
+
return handler;
|
|
37
|
+
},
|
|
38
|
+
set handler(next) {
|
|
39
|
+
handler = next;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Upstream has no timeout on `waitForSocketOpen`; the bridge requires one, so
|
|
45
|
+
* one has to be chosen.
|
|
46
|
+
*
|
|
47
|
+
* It is the core's own transport connect ceiling, not `connectTimeoutMs`. That
|
|
48
|
+
* config reaches neither the transport nor the core, so a value below the
|
|
49
|
+
* ceiling would reject a wait while the attempt behind it was still running and
|
|
50
|
+
* about to succeed. A value above it would sit past the point the attempt was
|
|
51
|
+
* already abandoned.
|
|
52
|
+
*/
|
|
53
|
+
const TRANSPORT_CONNECT_TIMEOUT_MS = 20000;
|
|
54
|
+
export const makeInternalMethods = (ctx) => {
|
|
55
|
+
/** Warned once per socket rather than per call, as with the other no-ops. */
|
|
56
|
+
let warnedAboutResync = false;
|
|
57
|
+
return {
|
|
58
|
+
/**
|
|
59
|
+
* `waitForSocket`, not `waitForConnected`: upstream waits for the socket
|
|
60
|
+
* to open, which is not the same as being logged in, and the bridge
|
|
61
|
+
* separates the two.
|
|
62
|
+
*
|
|
63
|
+
* A rejection means the socket did not open within one connect attempt,
|
|
64
|
+
* not that it never will: the engine reconnects on its own, and a caller
|
|
65
|
+
* that wants the next attempt waits again.
|
|
66
|
+
*/
|
|
67
|
+
waitForSocketOpen: async () => {
|
|
68
|
+
await (await ctx.getClient()).waitForSocket(TRANSPORT_CONNECT_TIMEOUT_MS);
|
|
69
|
+
},
|
|
70
|
+
/**
|
|
71
|
+
* Publishes a message onto the event bus, which is this layer's own job.
|
|
72
|
+
* Buffered as upstream buffers it, so a replay of many messages
|
|
73
|
+
* consolidates into the batches a listener expects rather than one
|
|
74
|
+
* event per call.
|
|
75
|
+
*
|
|
76
|
+
* The push-name half of upstream's version is not reproduced: contact
|
|
77
|
+
* state belongs to the core, and writing it from here would make two
|
|
78
|
+
* writers for one value.
|
|
79
|
+
*/
|
|
80
|
+
upsertMessage: ctx.ev.createBufferedFunction(async (msg, type) => {
|
|
81
|
+
ctx.ev.emit('messages.upsert', { messages: [msg], type });
|
|
82
|
+
}),
|
|
83
|
+
/**
|
|
84
|
+
* The same reporter the socket's own failure paths use, rather than a
|
|
85
|
+
* second one that only a consumer could reach: a dispatcher that threw
|
|
86
|
+
* or a wire batch that would not decode arrives here. The socket
|
|
87
|
+
* redefines this as an accessor, so assigning to it replaces the
|
|
88
|
+
* handler those paths report through.
|
|
89
|
+
*/
|
|
90
|
+
onUnexpectedError: (err, msg) => {
|
|
91
|
+
ctx.reportUnexpectedError(err, msg);
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Resolves without forcing anything, and says so once.
|
|
95
|
+
*
|
|
96
|
+
* The engine syncs app state on connect and re-syncs every collection
|
|
97
|
+
* when the server raises the `syncd_app_state` dirty bit, so the state a
|
|
98
|
+
* caller wants current already is. There is no on-demand resync to
|
|
99
|
+
* delegate to, and rejecting would break a call whose intent is met.
|
|
100
|
+
*/
|
|
101
|
+
resyncAppState: async (collections, isInitialSync) => {
|
|
102
|
+
void collections;
|
|
103
|
+
void isInitialSync;
|
|
104
|
+
if (!warnedAboutResync) {
|
|
105
|
+
warnedAboutResync = true;
|
|
106
|
+
ctx.logger.warn('resyncAppState is a no-op: the engine syncs app state on connect and again whenever the server marks it dirty');
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* Refused: the offset is protocol state the core keeps from the stanzas
|
|
111
|
+
* it already reads. A second clock here would drift from the one that
|
|
112
|
+
* actually timestamps outgoing messages.
|
|
113
|
+
*/
|
|
114
|
+
updateServerTimeOffset: (node) => {
|
|
115
|
+
void node;
|
|
116
|
+
throw new Boom('updateServerTimeOffset is not supported: the engine tracks the server clock offset itself, and a second one here would diverge from the one it stamps messages with', { statusCode: 501 });
|
|
117
|
+
},
|
|
118
|
+
/**
|
|
119
|
+
* Refused one layer down. The core's session instance is `pub(crate)`,
|
|
120
|
+
* and what exists returns a half-built stanza plus a sequence number, so
|
|
121
|
+
* exposing it would hand JavaScript the job of finishing and sequencing
|
|
122
|
+
* a lifecycle stanza.
|
|
123
|
+
*/
|
|
124
|
+
sendUnifiedSession: async () => {
|
|
125
|
+
throw new Boom('sendUnifiedSession is not supported: it is connection lifecycle machinery the engine owns, not a consumer operation', { statusCode: 501 });
|
|
126
|
+
},
|
|
127
|
+
/**
|
|
128
|
+
* Refused: the bridge exposes app-state actions typed per action and
|
|
129
|
+
* deliberately no generic. Accepting a raw patch here would mean
|
|
130
|
+
* building mutation indices and schema versions in TypeScript, beside
|
|
131
|
+
* the copy the core already maintains.
|
|
132
|
+
*/
|
|
133
|
+
appPatch: async (patchCreate) => {
|
|
134
|
+
void patchCreate;
|
|
135
|
+
throw new Boom('appPatch is not supported: use the typed chatModify variants, which is the only app-state surface this package can offer without a second implementation of the patch format', { statusCode: 501 });
|
|
136
|
+
},
|
|
137
|
+
/**
|
|
138
|
+
* Null rather than absent, and rather than a shadow. Retry is the
|
|
139
|
+
* engine's, so there is no manager here to hand out, and saying so in
|
|
140
|
+
* the type is more useful than leaving the field missing.
|
|
141
|
+
*/
|
|
142
|
+
messageRetryManager: null
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=internals.js.map
|
package/lib/Socket/messages.d.ts
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import type { AnyMessageContent, MessageGenerationOptions, MessageReceiptType, MessageRelayOptions, WAMessage,
|
|
1
|
+
import type { AnyMessageContent, MessageGenerationOptions, MessageReceiptType, MessageRelayOptions, WAMessage, WAMessageKey } from '../Types/index.js';
|
|
2
2
|
import { WAProto } from '../Types/index.js';
|
|
3
3
|
import type { SocketContext } from './types.js';
|
|
4
|
-
/**
|
|
5
|
-
* Drop `messageContextInfo` before handing the proto to the Rust bridge so the
|
|
6
|
-
* bridge can fill in its own `messageSecret` / `reportingTokenVersion`.
|
|
7
|
-
*
|
|
8
|
-
* Exception: pin messages need `messageAddOnDurationInSecs` (86400 / 604800 /
|
|
9
|
-
* 2592000 to pin, 0 to unpin). The bridge does not set this field, so we save
|
|
10
|
-
* it across the delete and restore it on a fresh contextInfo.
|
|
11
|
-
*
|
|
12
|
-
* Mutates `msg` in place.
|
|
13
|
-
*
|
|
14
|
-
* `contentType` is a parameter so the send path can hand over the type it has
|
|
15
|
-
* already resolved rather than have it scanned out of `msg` a second time.
|
|
16
|
-
*/
|
|
17
|
-
export declare function stripContextInfoForBridge(msg: WAMessageContent, contentType?: keyof WAProto.IMessage | undefined): void;
|
|
18
4
|
export declare const makeMessageMethods: (ctx: SocketContext) => {
|
|
19
5
|
sendMessage: (jid: string, content: AnyMessageContent, options?: Omit<MessageGenerationOptions, 'waClient' | 'logger' | 'userJid' | 'mediaInNote'>) => Promise<WAMessage>;
|
|
20
6
|
updateMediaMessage: (message: WAMessage) => Promise<WAMessage>;
|
package/lib/Socket/messages.js
CHANGED
|
@@ -13,26 +13,6 @@ function getMediaContent(content) {
|
|
|
13
13
|
content?.documentMessage ||
|
|
14
14
|
content?.stickerMessage);
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Drop `messageContextInfo` before handing the proto to the Rust bridge so the
|
|
18
|
-
* bridge can fill in its own `messageSecret` / `reportingTokenVersion`.
|
|
19
|
-
*
|
|
20
|
-
* Exception: pin messages need `messageAddOnDurationInSecs` (86400 / 604800 /
|
|
21
|
-
* 2592000 to pin, 0 to unpin). The bridge does not set this field, so we save
|
|
22
|
-
* it across the delete and restore it on a fresh contextInfo.
|
|
23
|
-
*
|
|
24
|
-
* Mutates `msg` in place.
|
|
25
|
-
*
|
|
26
|
-
* `contentType` is a parameter so the send path can hand over the type it has
|
|
27
|
-
* already resolved rather than have it scanned out of `msg` a second time.
|
|
28
|
-
*/
|
|
29
|
-
export function stripContextInfoForBridge(msg, contentType = getContentType(msg)) {
|
|
30
|
-
const pinAddOnDuration = contentType === 'pinInChatMessage' ? msg.messageContextInfo?.messageAddOnDurationInSecs : undefined;
|
|
31
|
-
delete msg.messageContextInfo;
|
|
32
|
-
if (pinAddOnDuration !== undefined && pinAddOnDuration !== null) {
|
|
33
|
-
msg.messageContextInfo = { messageAddOnDurationInSecs: pinAddOnDuration };
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
16
|
const normalizedUserJids = new WeakMap();
|
|
37
17
|
const getNormalizedUserJid = (ctx) => {
|
|
38
18
|
const userId = ctx.getUser()?.id;
|
|
@@ -87,7 +67,6 @@ export const makeMessageMethods = (ctx) => ({
|
|
|
87
67
|
return fullMsg;
|
|
88
68
|
}
|
|
89
69
|
}
|
|
90
|
-
stripContextInfoForBridge(msg, contentType);
|
|
91
70
|
let msgId;
|
|
92
71
|
const msgBytes = encodeProto('Message', msg);
|
|
93
72
|
if (jid === 'status@broadcast' && options?.statusJidList?.length) {
|
|
@@ -155,7 +134,9 @@ export const makeMessageMethods = (ctx) => ({
|
|
|
155
134
|
messageId: plan.messageId,
|
|
156
135
|
extraNodes: plan.kind === 'retransmission' ? 0 : plan.nodes.length
|
|
157
136
|
}, 'relayMessage compatibility plan');
|
|
158
|
-
|
|
137
|
+
// The message goes to the bridge as the caller built it: the core settles
|
|
138
|
+
// messageSecret / reportingTokenVersion itself, reusing a caller-set secret
|
|
139
|
+
// rather than replacing it, so nothing here has to be dropped.
|
|
159
140
|
const bytes = encodeProto('Message', message);
|
|
160
141
|
if (plan.kind === 'retransmission') {
|
|
161
142
|
await client.retransmitMessageBytes(jid, bytes, plan.input);
|