@twsxtd/baileys 7.0.0-rc.9.commit.7a91cac1d4ec → 7.0.0-rc.9.commit.8d1e795328c7
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/WAProto/fix-imports.js +22 -18
- package/WAProto/index.js +22 -18
- package/lib/Defaults/index.d.ts +2 -0
- package/lib/Defaults/index.d.ts.map +1 -1
- package/lib/Defaults/index.js +3 -1
- package/lib/Defaults/index.js.map +1 -1
- package/lib/Signal/libsignal.d.ts.map +1 -1
- package/lib/Signal/libsignal.js +15 -12
- package/lib/Signal/libsignal.js.map +1 -1
- package/lib/Signal/lid-mapping.d.ts +3 -5
- package/lib/Signal/lid-mapping.d.ts.map +1 -1
- package/lib/Signal/lid-mapping.js +37 -22
- package/lib/Signal/lid-mapping.js.map +1 -1
- package/lib/Socket/Client/websocket.d.ts.map +1 -1
- package/lib/Socket/Client/websocket.js +3 -6
- package/lib/Socket/Client/websocket.js.map +1 -1
- package/lib/Socket/business.d.ts +7 -4
- package/lib/Socket/business.d.ts.map +1 -1
- package/lib/Socket/chats.d.ts +9 -3
- package/lib/Socket/chats.d.ts.map +1 -1
- package/lib/Socket/chats.js +253 -47
- package/lib/Socket/chats.js.map +1 -1
- package/lib/Socket/communities.d.ts +7 -4
- package/lib/Socket/communities.d.ts.map +1 -1
- package/lib/Socket/groups.d.ts +8 -4
- package/lib/Socket/groups.d.ts.map +1 -1
- package/lib/Socket/groups.js +20 -0
- package/lib/Socket/groups.js.map +1 -1
- package/lib/Socket/index.d.ts +7 -4
- package/lib/Socket/index.d.ts.map +1 -1
- package/lib/Socket/messages-recv.d.ts +7 -4
- package/lib/Socket/messages-recv.d.ts.map +1 -1
- package/lib/Socket/messages-recv.js +296 -103
- package/lib/Socket/messages-recv.js.map +1 -1
- package/lib/Socket/messages-send.d.ts +7 -4
- package/lib/Socket/messages-send.d.ts.map +1 -1
- package/lib/Socket/messages-send.js +113 -50
- package/lib/Socket/messages-send.js.map +1 -1
- package/lib/Socket/newsletter.d.ts +6 -3
- package/lib/Socket/newsletter.d.ts.map +1 -1
- package/lib/Socket/newsletter.js +2 -2
- package/lib/Socket/newsletter.js.map +1 -1
- package/lib/Socket/socket.d.ts +0 -2
- package/lib/Socket/socket.d.ts.map +1 -1
- package/lib/Socket/socket.js +15 -9
- package/lib/Socket/socket.js.map +1 -1
- package/lib/Types/Auth.d.ts +2 -0
- package/lib/Types/Auth.d.ts.map +1 -1
- package/lib/Types/Call.d.ts +1 -1
- package/lib/Types/Call.d.ts.map +1 -1
- package/lib/Types/Contact.d.ts +2 -0
- package/lib/Types/Contact.d.ts.map +1 -1
- package/lib/Types/Events.d.ts +16 -0
- package/lib/Types/Events.d.ts.map +1 -1
- package/lib/Types/GroupMetadata.d.ts +4 -0
- package/lib/Types/GroupMetadata.d.ts.map +1 -1
- package/lib/Types/Message.d.ts +15 -2
- package/lib/Types/Message.d.ts.map +1 -1
- package/lib/Types/Message.js.map +1 -1
- package/lib/Types/Newsletter.d.ts +4 -2
- package/lib/Types/Newsletter.d.ts.map +1 -1
- package/lib/Types/Newsletter.js +4 -2
- package/lib/Types/Newsletter.js.map +1 -1
- package/lib/Types/Signal.d.ts +1 -2
- package/lib/Types/Signal.d.ts.map +1 -1
- package/lib/Utils/auth-utils.d.ts +5 -0
- package/lib/Utils/auth-utils.d.ts.map +1 -1
- package/lib/Utils/auth-utils.js +49 -14
- package/lib/Utils/auth-utils.js.map +1 -1
- package/lib/Utils/chat-utils.d.ts +30 -0
- package/lib/Utils/chat-utils.d.ts.map +1 -1
- package/lib/Utils/chat-utils.js +34 -8
- package/lib/Utils/chat-utils.js.map +1 -1
- package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
- package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
- package/lib/Utils/companion-reg-client-utils.js +41 -0
- package/lib/Utils/companion-reg-client-utils.js.map +1 -0
- package/lib/Utils/decode-wa-message.d.ts +12 -0
- package/lib/Utils/decode-wa-message.d.ts.map +1 -1
- package/lib/Utils/decode-wa-message.js +22 -0
- package/lib/Utils/decode-wa-message.js.map +1 -1
- package/lib/Utils/event-buffer.d.ts +0 -7
- package/lib/Utils/event-buffer.d.ts.map +1 -1
- package/lib/Utils/event-buffer.js +9 -29
- package/lib/Utils/event-buffer.js.map +1 -1
- package/lib/Utils/generics.d.ts +1 -0
- package/lib/Utils/generics.d.ts.map +1 -1
- package/lib/Utils/generics.js +22 -1
- package/lib/Utils/generics.js.map +1 -1
- package/lib/Utils/history.d.ts.map +1 -1
- package/lib/Utils/history.js +11 -9
- package/lib/Utils/history.js.map +1 -1
- package/lib/Utils/identity-change-handler.d.ts +7 -0
- package/lib/Utils/identity-change-handler.d.ts.map +1 -1
- package/lib/Utils/identity-change-handler.js +2 -6
- package/lib/Utils/identity-change-handler.js.map +1 -1
- package/lib/Utils/index.d.ts +15 -15
- package/lib/Utils/index.d.ts.map +1 -1
- package/lib/Utils/index.js +15 -15
- package/lib/Utils/index.js.map +1 -1
- package/lib/Utils/message-retry-manager.d.ts +1 -5
- package/lib/Utils/message-retry-manager.d.ts.map +1 -1
- package/lib/Utils/message-retry-manager.js +7 -14
- package/lib/Utils/message-retry-manager.js.map +1 -1
- package/lib/Utils/messages-media.js +1 -1
- package/lib/Utils/messages-media.js.map +1 -1
- package/lib/Utils/messages.d.ts.map +1 -1
- package/lib/Utils/messages.js +22 -1
- package/lib/Utils/messages.js.map +1 -1
- package/lib/Utils/process-message.d.ts.map +1 -1
- package/lib/Utils/process-message.js +74 -7
- package/lib/Utils/process-message.js.map +1 -1
- package/lib/Utils/sync-action-utils.d.ts.map +1 -1
- package/lib/Utils/sync-action-utils.js +1 -0
- package/lib/Utils/sync-action-utils.js.map +1 -1
- package/lib/Utils/tc-token-utils.d.ts +26 -1
- package/lib/Utils/tc-token-utils.d.ts.map +1 -1
- package/lib/Utils/tc-token-utils.js +149 -4
- package/lib/Utils/tc-token-utils.js.map +1 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +26 -3
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -1
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/index.d.ts +1 -0
- package/lib/WAUSync/Protocols/index.d.ts.map +1 -1
- package/lib/WAUSync/Protocols/index.js +1 -0
- package/lib/WAUSync/Protocols/index.js.map +1 -1
- package/lib/WAUSync/USyncQuery.d.ts +1 -0
- package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
- package/lib/WAUSync/USyncQuery.js +5 -1
- package/lib/WAUSync/USyncQuery.js.map +1 -1
- package/lib/WAUSync/USyncUser.d.ts +4 -0
- package/lib/WAUSync/USyncUser.d.ts.map +1 -1
- package/lib/WAUSync/USyncUser.js +8 -0
- package/lib/WAUSync/USyncUser.js.map +1 -1
- package/package.json +5 -3
package/lib/Socket/business.d.ts
CHANGED
|
@@ -19,13 +19,14 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
19
19
|
updateBussinesProfile: (args: UpdateBussinesProfileProps) => Promise<any>;
|
|
20
20
|
updateCoverPhoto: (photo: WAMediaUpload) => Promise<number>;
|
|
21
21
|
removeCoverPhoto: (id: string) => Promise<any>;
|
|
22
|
+
end: (error: Error | undefined) => Promise<void>;
|
|
22
23
|
sendMessageAck: (node: BinaryNode, errorCode?: number) => Promise<void>;
|
|
23
24
|
sendRetryRequest: (node: BinaryNode, forceIncludeKeys?: boolean) => Promise<void>;
|
|
24
25
|
rejectCall: (callId: string, callFrom: string) => Promise<void>;
|
|
25
26
|
fetchMessageHistory: (count: number, oldestMsgKey: import("../index.js").WAMessageKey, oldestMsgTimestamp: number | Long) => Promise<string>;
|
|
26
27
|
requestPlaceholderResend: (messageKey: import("../index.js").WAMessageKey, msgData?: Partial<import("../index.js").WAMessage>) => Promise<string | undefined>;
|
|
27
28
|
messageRetryManager: import("../index.js").MessageRetryManager | null;
|
|
28
|
-
|
|
29
|
+
issuePrivacyTokens: (jids: string[], timestamp?: number) => Promise<any>;
|
|
29
30
|
assertSessions: (jids: string[], force?: boolean) => Promise<boolean>;
|
|
30
31
|
relayMessage: (jid: string, message: import("../index.js").proto.IMessage, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }: import("../index.js").MessageRelayOptions) => Promise<string>;
|
|
31
32
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: import("../index.js").MessageReceiptType) => Promise<void>;
|
|
@@ -100,6 +101,11 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
100
101
|
groupFetchAllParticipating: () => Promise<{
|
|
101
102
|
[_: string]: import("../index.js").GroupMetadata;
|
|
102
103
|
}>;
|
|
104
|
+
serverProps: {
|
|
105
|
+
privacyTokenOn1to1: boolean;
|
|
106
|
+
profilePicPrivacyToken: boolean;
|
|
107
|
+
lidTrustedTokenIssueToLid: boolean;
|
|
108
|
+
};
|
|
103
109
|
createCallLink: (type: "audio" | "video", event?: {
|
|
104
110
|
startTime: number;
|
|
105
111
|
}, timeoutMs?: number) => Promise<string | undefined>;
|
|
@@ -167,8 +173,6 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
167
173
|
createBufferedFunction<A extends any[], T>(work: (...args: A) => Promise<T>): (...args: A) => Promise<T>;
|
|
168
174
|
flush(): boolean;
|
|
169
175
|
isBuffering(): boolean;
|
|
170
|
-
release(): void;
|
|
171
|
-
removeAllListeners<T extends keyof import("../index.js").BaileysEventMap>(event?: T): void;
|
|
172
176
|
};
|
|
173
177
|
authState: {
|
|
174
178
|
creds: import("../index.js").AuthenticationCreds;
|
|
@@ -183,7 +187,6 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
183
187
|
sendRawMessage: (data: Uint8Array | Buffer) => Promise<void>;
|
|
184
188
|
sendNode: (frame: BinaryNode) => Promise<void>;
|
|
185
189
|
logout: (msg?: string) => Promise<void>;
|
|
186
|
-
end: (error: Error | undefined) => Promise<void>;
|
|
187
190
|
onUnexpectedError: (err: Error | import("@hapi/boom").Boom, msg: string) => void;
|
|
188
191
|
uploadPreKeys: (count?: number, retryCount?: number) => Promise<void>;
|
|
189
192
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business.d.ts","sourceRoot":"","sources":["../../src/Socket/business.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC5G,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AAUnE,OAAO,EAAE,KAAK,UAAU,EAAqC,MAAM,aAAa,CAAA;AAIhF,eAAO,MAAM,kBAAkB,GAAI,QAAQ,YAAY;;+BA8Od,MAAM,eAAe,MAAM;yCAjGjB,iBAAiB;;;;2BAmD/B,MAAM;;;4BAkIL,aAAa;gCAwCT,MAAM,EAAE;;;+BA9ET,MAAM,UAAU,aAAa;kCAxR1B,0BAA0B;8BA2E9B,aAAa;2BAoChB,MAAM
|
|
1
|
+
{"version":3,"file":"business.d.ts","sourceRoot":"","sources":["../../src/Socket/business.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC5G,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AAUnE,OAAO,EAAE,KAAK,UAAU,EAAqC,MAAM,aAAa,CAAA;AAIhF,eAAO,MAAM,kBAAkB,GAAI,QAAQ,YAAY;;+BA8Od,MAAM,eAAe,MAAM;yCAjGjB,iBAAiB;;;;2BAmD/B,MAAM;;;4BAkIL,aAAa;gCAwCT,MAAM,EAAE;;;+BA9ET,MAAM,UAAU,aAAa;kCAxR1B,0BAA0B;8BA2E9B,aAAa;2BAoChB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsS+5oB,CAAC;;;;;;;;;0DApXv7oB,GAAG,0BAEV,GACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgXC,CAAA"}
|
package/lib/Socket/chats.d.ts
CHANGED
|
@@ -6,6 +6,15 @@ import type { LabelActionBody } from '../Types/Label.js';
|
|
|
6
6
|
import { type BinaryNode } from '../WABinary/index.js';
|
|
7
7
|
import { USyncQuery } from '../WAUSync/index.js';
|
|
8
8
|
export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
9
|
+
serverProps: {
|
|
10
|
+
/** AB prop 10518: gate tctoken on 1:1 messages. Default true (safe: avoids 463). */
|
|
11
|
+
privacyTokenOn1to1: boolean;
|
|
12
|
+
/** AB prop 9666: gate tctoken on profile picture IQs. WA Web default: true. */
|
|
13
|
+
profilePicPrivacyToken: boolean;
|
|
14
|
+
/** AB prop 14303: issue tctokens to LID instead of PN. WA Web default: false. */
|
|
15
|
+
lidTrustedTokenIssueToLid: boolean;
|
|
16
|
+
};
|
|
17
|
+
end: (error: Error | undefined) => Promise<void>;
|
|
9
18
|
createCallLink: (type: "audio" | "video", event?: {
|
|
10
19
|
startTime: number;
|
|
11
20
|
}, timeoutMs?: number) => Promise<string | undefined>;
|
|
@@ -76,8 +85,6 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
76
85
|
createBufferedFunction<A extends any[], T>(work: (...args: A) => Promise<T>): (...args: A) => Promise<T>;
|
|
77
86
|
flush(): boolean;
|
|
78
87
|
isBuffering(): boolean;
|
|
79
|
-
release(): void;
|
|
80
|
-
removeAllListeners<T extends keyof import("../Types/index.js").BaileysEventMap>(event?: T): void;
|
|
81
88
|
};
|
|
82
89
|
authState: {
|
|
83
90
|
creds: import("../Types/index.js").AuthenticationCreds;
|
|
@@ -92,7 +99,6 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
92
99
|
sendRawMessage: (data: Uint8Array | Buffer) => Promise<void>;
|
|
93
100
|
sendNode: (frame: BinaryNode) => Promise<void>;
|
|
94
101
|
logout: (msg?: string) => Promise<void>;
|
|
95
|
-
end: (error: Error | undefined) => Promise<void>;
|
|
96
102
|
onUnexpectedError: (err: Error | Boom, msg: string) => void;
|
|
97
103
|
uploadPreKeys: (count?: number, retryCount?: number) => Promise<void>;
|
|
98
104
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../src/Socket/chats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAE9C,OAAO,KAAK,EACX,WAAW,EAEX,gBAAgB,EAGhB,iBAAiB,EAEjB,YAAY,EAEZ,iBAAiB,EACjB,aAAa,EACb,SAAS,EACT,aAAa,EAEb,UAAU,EACV,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,MAAM,UAAU,CAAA;AAEjB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../src/Socket/chats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAE9C,OAAO,KAAK,EACX,WAAW,EAEX,gBAAgB,EAGhB,iBAAiB,EAEjB,YAAY,EAEZ,iBAAiB,EACjB,aAAa,EACb,SAAS,EACT,aAAa,EAEb,UAAU,EACV,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,MAAM,UAAU,CAAA;AAEjB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAsBrD,OAAO,EACN,KAAK,UAAU,EAWf,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAa,MAAM,YAAY,CAAA;AAGlD,eAAO,MAAM,eAAe,GAAI,QAAQ,YAAY;;QA6BlD,oFAAoF;;QAEpF,+EAA+E;;QAE/E,iFAAiF;;;iBAg3C9D,KAAK,GAAG,SAAS;2BA7qBD,OAAO,GAAG,OAAO,UAAU;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,cAAc,MAAM;;;;;;;;;;;;;;;;;;4BA0HnE,aAAa;+BApGV,UAAU,UAAU,MAAM;+BA8C1B,MAAM;6BA5GR,MAAM,SAAQ,SAAS,GAAG,OAAO,cAA0B,MAAM;;2BAhdnE,MAAM,EAAE;yCAaM,MAAM,EAAE;gCAepD,MAAM,WACF,aAAa,eACT;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;gCAmCN,MAAM;kCA0BJ,MAAM;8BAkBV,MAAM;6BAkBP,MAAM,UAAU,OAAO,GAAG,SAAS;2DAkoBX,OAAO;+BAn1B7B,kBAAkB;mCAJd,sBAAsB;mCAQtB,cAAc;iCAIhB,oBAAoB;yCAIZ,cAAc;iCAItB,cAAc;uCAIR,mBAAmB;oCAItB,sBAAsB;8CAIZ,MAAM;8BAqPtB,MAAM,KAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;;sBA0jBxD,gBAAgB,OAAO,MAAM;2BAxgBlB,cAAc,GAAG,QAAQ,kBAAkB,MAAM,GAAG,MAAM;4BA2iB/D,MAAM,WAAW,KAAK,CAAC,eAAe,CAAC,cAAc;yBAYxD,MAAM;oBAYX,MAAM,UAAU,eAAe;wBAc3B,MAAM,WAAW,MAAM;2BAcpB,MAAM,WAAW,MAAM;2BAcvB,MAAM,aAAa,MAAM,WAAW,MAAM;8BAevC,MAAM,aAAa,MAAM,WAAW,MAAM;gBAhGxD,MAAM,YAAY;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,QAAQ,OAAO;sCA+G7C,gBAAgB;kCAYpB,MAAM;;;;;;0DAvnClB,GAAG,0BACzB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAo8CN,CAAA"}
|
package/lib/Socket/chats.js
CHANGED
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache';
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
3
|
import { proto } from '../../WAProto/index.js';
|
|
4
|
-
import { DEFAULT_CACHE_TTLS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
4
|
+
import { DEFAULT_CACHE_TTLS, HISTORY_SYNC_PAUSED_TIMEOUT_MS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
5
5
|
import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
|
|
6
6
|
import { SyncState } from '../Types/State.js';
|
|
7
|
-
import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, extractSyncdPatches, generateProfilePicture, getHistoryMsg, newLTHashState, processSyncAction } from '../Utils/index.js';
|
|
7
|
+
import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, ensureLTHashStateVersion, extractSyncdPatches, bindCleanupOnConnectionClose, generateProfilePicture, getHistoryMsg, isAppStateSyncIrrecoverable, isMissingKeyError, MAX_SYNC_ATTEMPTS, newLTHashState, processSyncAction } from '../Utils/index.js';
|
|
8
8
|
import { makeMutex } from '../Utils/make-mutex.js';
|
|
9
9
|
import processMessage from '../Utils/process-message.js';
|
|
10
10
|
import { buildTcTokenFromJid } from '../Utils/tc-token-utils.js';
|
|
11
|
-
import { getBinaryNodeChild, getBinaryNodeChildren, jidDecode, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
11
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, isLidUser, isPnUser, jidDecode, jidNormalizedUser, isHostedLidUser, isHostedPnUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
12
12
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
13
13
|
import { makeSocket } from './socket.js';
|
|
14
|
-
const MAX_SYNC_ATTEMPTS = 2;
|
|
15
14
|
export const makeChatsSocket = (config) => {
|
|
16
15
|
const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
|
|
17
16
|
const sock = makeSocket(config);
|
|
18
17
|
const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession } = sock;
|
|
18
|
+
const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
|
|
19
19
|
let privacySettings;
|
|
20
|
+
/** Server-assigned AB props for protocol behavior. */
|
|
21
|
+
const serverProps = {
|
|
22
|
+
/** AB prop 10518: gate tctoken on 1:1 messages. Default true (safe: avoids 463). */
|
|
23
|
+
privacyTokenOn1to1: true,
|
|
24
|
+
/** AB prop 9666: gate tctoken on profile picture IQs. WA Web default: true. */
|
|
25
|
+
profilePicPrivacyToken: true,
|
|
26
|
+
/** AB prop 14303: issue tctokens to LID instead of PN. WA Web default: false. */
|
|
27
|
+
lidTrustedTokenIssueToLid: false
|
|
28
|
+
};
|
|
20
29
|
let syncState = SyncState.Connecting;
|
|
21
30
|
/** this mutex ensures that messages are processed in order */
|
|
22
31
|
const messageMutex = makeMutex();
|
|
@@ -28,15 +37,44 @@ export const makeChatsSocket = (config) => {
|
|
|
28
37
|
const notificationMutex = makeMutex();
|
|
29
38
|
// Timeout for AwaitingInitialSync state
|
|
30
39
|
let awaitingSyncTimeout;
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
// In-memory history sync completion tracking (resets on reconnection)
|
|
41
|
+
const historySyncStatus = {
|
|
42
|
+
initialBootstrapComplete: false,
|
|
43
|
+
recentSyncComplete: false
|
|
44
|
+
};
|
|
45
|
+
let historySyncPausedTimeout;
|
|
46
|
+
// Collections blocked on missing app state sync keys (mirrors WA Web's "Blocked" state).
|
|
47
|
+
// When a key arrives via APP_STATE_SYNC_KEY_SHARE, these are re-synced.
|
|
48
|
+
const blockedCollections = new Set();
|
|
49
|
+
const internalPlaceholderResendCache = config.placeholderResendCache
|
|
50
|
+
? undefined
|
|
51
|
+
: new NodeCache({
|
|
33
52
|
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
34
|
-
useClones: false
|
|
35
|
-
maxKeys: 5000
|
|
53
|
+
useClones: false
|
|
36
54
|
});
|
|
55
|
+
const placeholderResendCache = config.placeholderResendCache || internalPlaceholderResendCache;
|
|
37
56
|
if (!config.placeholderResendCache) {
|
|
38
57
|
config.placeholderResendCache = placeholderResendCache;
|
|
39
58
|
}
|
|
59
|
+
let cleanedUp = false;
|
|
60
|
+
const cleanupInternalResources = async () => {
|
|
61
|
+
if (cleanedUp) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
cleanedUp = true;
|
|
65
|
+
if (awaitingSyncTimeout) {
|
|
66
|
+
clearTimeout(awaitingSyncTimeout);
|
|
67
|
+
awaitingSyncTimeout = undefined;
|
|
68
|
+
}
|
|
69
|
+
if (historySyncPausedTimeout) {
|
|
70
|
+
clearTimeout(historySyncPausedTimeout);
|
|
71
|
+
historySyncPausedTimeout = undefined;
|
|
72
|
+
}
|
|
73
|
+
if (internalPlaceholderResendCache) {
|
|
74
|
+
await Promise.resolve(internalPlaceholderResendCache.close());
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
bindCleanupOnConnectionClose(ev, cleanupInternalResources);
|
|
40
78
|
/** helper function to fetch the given app state sync key */
|
|
41
79
|
const getAppStateSyncKey = async (keyId) => {
|
|
42
80
|
const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId]);
|
|
@@ -259,6 +297,42 @@ export const makeChatsSocket = (config) => {
|
|
|
259
297
|
return getBinaryNodeChildren(listNode, 'item').map(n => n.attrs.jid);
|
|
260
298
|
};
|
|
261
299
|
const updateBlockStatus = async (jid, action) => {
|
|
300
|
+
const normalizedJid = jidNormalizedUser(jid);
|
|
301
|
+
let lid;
|
|
302
|
+
let pn_jid;
|
|
303
|
+
if (isLidUser(normalizedJid) || isHostedLidUser(normalizedJid)) {
|
|
304
|
+
lid = normalizedJid;
|
|
305
|
+
if (action === 'block') {
|
|
306
|
+
const pn = await signalRepository.lidMapping.getPNForLID(normalizedJid);
|
|
307
|
+
if (!pn) {
|
|
308
|
+
throw new Boom(`Unable to resolve PN JID for LID: ${jid}`, { statusCode: 400 });
|
|
309
|
+
}
|
|
310
|
+
pn_jid = jidNormalizedUser(pn);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
else if (isPnUser(normalizedJid) || isHostedPnUser(normalizedJid)) {
|
|
314
|
+
const mapped = await signalRepository.lidMapping.getLIDForPN(normalizedJid);
|
|
315
|
+
if (!mapped) {
|
|
316
|
+
throw new Boom(`Unable to resolve LID for PN JID: ${jid}`, { statusCode: 400 });
|
|
317
|
+
}
|
|
318
|
+
lid = mapped;
|
|
319
|
+
if (action === 'block') {
|
|
320
|
+
pn_jid = jidNormalizedUser(normalizedJid);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
throw new Boom(`Invalid jid: ${jid}`, { statusCode: 400 });
|
|
325
|
+
}
|
|
326
|
+
const itemAttrs = {
|
|
327
|
+
action,
|
|
328
|
+
jid: lid
|
|
329
|
+
};
|
|
330
|
+
if (action === 'block') {
|
|
331
|
+
if (!pn_jid) {
|
|
332
|
+
throw new Boom(`pn_jid required for block: ${jid}`, { statusCode: 400 });
|
|
333
|
+
}
|
|
334
|
+
itemAttrs.pn_jid = pn_jid;
|
|
335
|
+
}
|
|
262
336
|
await query({
|
|
263
337
|
tag: 'iq',
|
|
264
338
|
attrs: {
|
|
@@ -269,10 +343,7 @@ export const makeChatsSocket = (config) => {
|
|
|
269
343
|
content: [
|
|
270
344
|
{
|
|
271
345
|
tag: 'item',
|
|
272
|
-
attrs:
|
|
273
|
-
action,
|
|
274
|
-
jid
|
|
275
|
-
}
|
|
346
|
+
attrs: itemAttrs
|
|
276
347
|
}
|
|
277
348
|
]
|
|
278
349
|
});
|
|
@@ -371,6 +442,9 @@ export const makeChatsSocket = (config) => {
|
|
|
371
442
|
const collectionsToHandle = new Set(collections);
|
|
372
443
|
// in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
|
|
373
444
|
const attemptsMap = {};
|
|
445
|
+
// collections that failed and need a full snapshot on retry
|
|
446
|
+
// mirrors WA Web's ErrorFatal -> force snapshot behavior
|
|
447
|
+
const forceSnapshotCollections = new Set();
|
|
374
448
|
// keep executing till all collections are done
|
|
375
449
|
// sometimes a single patch request will not return all the patches (God knows why)
|
|
376
450
|
// so we fetch till they're all done (this is determined by the "has_more_patches" flag)
|
|
@@ -381,6 +455,7 @@ export const makeChatsSocket = (config) => {
|
|
|
381
455
|
const result = await authState.keys.get('app-state-sync-version', [name]);
|
|
382
456
|
let state = result[name];
|
|
383
457
|
if (state) {
|
|
458
|
+
state = ensureLTHashStateVersion(state);
|
|
384
459
|
if (typeof initialVersionMap[name] === 'undefined') {
|
|
385
460
|
initialVersionMap[name] = state.version;
|
|
386
461
|
}
|
|
@@ -389,14 +464,18 @@ export const makeChatsSocket = (config) => {
|
|
|
389
464
|
state = newLTHashState();
|
|
390
465
|
}
|
|
391
466
|
states[name] = state;
|
|
392
|
-
|
|
467
|
+
const shouldForceSnapshot = forceSnapshotCollections.has(name);
|
|
468
|
+
if (shouldForceSnapshot) {
|
|
469
|
+
forceSnapshotCollections.delete(name);
|
|
470
|
+
}
|
|
471
|
+
logger.info(`resyncing ${name} from v${state.version}${shouldForceSnapshot ? ' (forcing snapshot)' : ''}`);
|
|
393
472
|
nodes.push({
|
|
394
473
|
tag: 'collection',
|
|
395
474
|
attrs: {
|
|
396
475
|
name,
|
|
397
476
|
version: state.version.toString(),
|
|
398
|
-
// return snapshot if
|
|
399
|
-
return_snapshot: (!state.version).toString()
|
|
477
|
+
// return snapshot if syncing from scratch or forcing after a failed attempt
|
|
478
|
+
return_snapshot: (shouldForceSnapshot || !state.version).toString()
|
|
400
479
|
}
|
|
401
480
|
});
|
|
402
481
|
}
|
|
@@ -445,19 +524,37 @@ export const makeChatsSocket = (config) => {
|
|
|
445
524
|
}
|
|
446
525
|
}
|
|
447
526
|
catch (error) {
|
|
448
|
-
// if retry attempts overshoot
|
|
449
|
-
// or key not found
|
|
450
|
-
const isIrrecoverableError = attemptsMap[name] >= MAX_SYNC_ATTEMPTS ||
|
|
451
|
-
error.output?.statusCode === 404 ||
|
|
452
|
-
error.name === 'TypeError';
|
|
453
|
-
logger.info({ name, error: error.stack }, `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`);
|
|
454
|
-
await authState.keys.set({ 'app-state-sync-version': { [name]: null } });
|
|
455
|
-
// increment number of retries
|
|
456
527
|
attemptsMap[name] = (attemptsMap[name] || 0) + 1;
|
|
457
|
-
|
|
458
|
-
|
|
528
|
+
const logData = {
|
|
529
|
+
name,
|
|
530
|
+
attempt: attemptsMap[name],
|
|
531
|
+
version: states[name].version,
|
|
532
|
+
statusCode: error.output?.statusCode,
|
|
533
|
+
errorType: error.name,
|
|
534
|
+
error: error.stack
|
|
535
|
+
};
|
|
536
|
+
if (isMissingKeyError(error) && attemptsMap[name] >= MAX_SYNC_ATTEMPTS) {
|
|
537
|
+
// WA Web treats missing keys as "Blocked" — park the collection
|
|
538
|
+
// until the key arrives via APP_STATE_SYNC_KEY_SHARE.
|
|
539
|
+
logger.warn(logData, `${name} blocked on missing key from v${states[name].version}, parking after ${attemptsMap[name]} attempts`);
|
|
540
|
+
blockedCollections.add(name);
|
|
541
|
+
collectionsToHandle.delete(name);
|
|
542
|
+
}
|
|
543
|
+
else if (isMissingKeyError(error)) {
|
|
544
|
+
// Retry with a snapshot which may use a different key.
|
|
545
|
+
logger.info(logData, `${name} blocked on missing key from v${states[name].version}, retrying with snapshot`);
|
|
546
|
+
forceSnapshotCollections.add(name);
|
|
547
|
+
}
|
|
548
|
+
else if (isAppStateSyncIrrecoverable(error, attemptsMap[name])) {
|
|
549
|
+
logger.warn(logData, `failed to sync ${name} from v${states[name].version}, giving up`);
|
|
459
550
|
collectionsToHandle.delete(name);
|
|
460
551
|
}
|
|
552
|
+
else {
|
|
553
|
+
logger.info(logData, `failed to sync ${name} from v${states[name].version}, forcing snapshot retry`);
|
|
554
|
+
// force a full snapshot on retry to recover from
|
|
555
|
+
// corrupted local state (e.g. LTHash MAC mismatch)
|
|
556
|
+
forceSnapshotCollections.add(name);
|
|
557
|
+
}
|
|
461
558
|
}
|
|
462
559
|
}
|
|
463
560
|
}
|
|
@@ -474,7 +571,22 @@ export const makeChatsSocket = (config) => {
|
|
|
474
571
|
*/
|
|
475
572
|
const profilePictureUrl = async (jid, type = 'preview', timeoutMs) => {
|
|
476
573
|
const baseContent = [{ tag: 'picture', attrs: { type, query: 'url' } }];
|
|
477
|
-
|
|
574
|
+
// WA Web only includes tctoken for user JIDs (not groups/newsletters)
|
|
575
|
+
// and never for own profile pic (Chat model for self has no tcToken).
|
|
576
|
+
// Including tctoken for own JID causes the server to never respond.
|
|
577
|
+
const normalizedJid = jidNormalizedUser(jid);
|
|
578
|
+
const isUserJid = isPnUser(normalizedJid) || isLidUser(normalizedJid);
|
|
579
|
+
const me = authState.creds.me;
|
|
580
|
+
const isSelf = me && (normalizedJid === jidNormalizedUser(me.id) || (me.lid && normalizedJid === jidNormalizedUser(me.lid)));
|
|
581
|
+
let content = baseContent;
|
|
582
|
+
if (serverProps.profilePicPrivacyToken && isUserJid && !isSelf) {
|
|
583
|
+
content = await buildTcTokenFromJid({
|
|
584
|
+
authState,
|
|
585
|
+
jid: normalizedJid,
|
|
586
|
+
baseContent,
|
|
587
|
+
getLIDForPN
|
|
588
|
+
});
|
|
589
|
+
}
|
|
478
590
|
jid = jidNormalizedUser(jid);
|
|
479
591
|
const result = await query({
|
|
480
592
|
tag: 'iq',
|
|
@@ -484,7 +596,7 @@ export const makeChatsSocket = (config) => {
|
|
|
484
596
|
type: 'get',
|
|
485
597
|
xmlns: 'w:profile:picture'
|
|
486
598
|
},
|
|
487
|
-
content
|
|
599
|
+
content
|
|
488
600
|
}, timeoutMs);
|
|
489
601
|
const child = getBinaryNodeChild(result, 'picture');
|
|
490
602
|
return child?.attrs?.url;
|
|
@@ -550,7 +662,12 @@ export const makeChatsSocket = (config) => {
|
|
|
550
662
|
* @param tcToken token for subscription, use if present
|
|
551
663
|
*/
|
|
552
664
|
const presenceSubscribe = async (toJid) => {
|
|
553
|
-
|
|
665
|
+
// Only include tctoken for user JIDs — groups/newsletters don't use tctokens
|
|
666
|
+
const normalizedToJid = jidNormalizedUser(toJid);
|
|
667
|
+
const isUserJid = isPnUser(normalizedToJid) || isLidUser(normalizedToJid);
|
|
668
|
+
const tcTokenContent = isUserJid
|
|
669
|
+
? await buildTcTokenFromJid({ authState, jid: normalizedToJid, getLIDForPN })
|
|
670
|
+
: undefined;
|
|
554
671
|
return sendNode({
|
|
555
672
|
tag: 'presence',
|
|
556
673
|
attrs: {
|
|
@@ -605,7 +722,7 @@ export const makeChatsSocket = (config) => {
|
|
|
605
722
|
logger.debug({ patch: patchCreate }, 'applying app patch');
|
|
606
723
|
await resyncAppState([name], false);
|
|
607
724
|
const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name]);
|
|
608
|
-
initial = currentSyncVersion
|
|
725
|
+
initial = currentSyncVersion ? ensureLTHashStateVersion(currentSyncVersion) : newLTHashState();
|
|
609
726
|
encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
|
|
610
727
|
const { patch, state } = encodeResult;
|
|
611
728
|
const node = {
|
|
@@ -651,22 +768,21 @@ export const makeChatsSocket = (config) => {
|
|
|
651
768
|
}
|
|
652
769
|
}
|
|
653
770
|
};
|
|
654
|
-
/**
|
|
771
|
+
/** fetch AB props */
|
|
655
772
|
const fetchProps = async () => {
|
|
656
|
-
//TODO: implement both protocol 1 and protocol 2 prop fetching, specially for abKey for WM
|
|
657
773
|
const resultNode = await query({
|
|
658
774
|
tag: 'iq',
|
|
659
775
|
attrs: {
|
|
660
776
|
to: S_WHATSAPP_NET,
|
|
661
|
-
xmlns: '
|
|
777
|
+
xmlns: 'abt',
|
|
662
778
|
type: 'get'
|
|
663
779
|
},
|
|
664
780
|
content: [
|
|
665
781
|
{
|
|
666
782
|
tag: 'props',
|
|
667
783
|
attrs: {
|
|
668
|
-
protocol: '
|
|
669
|
-
hash: authState
|
|
784
|
+
protocol: '1',
|
|
785
|
+
...(authState?.creds?.lastPropHash ? { hash: authState.creds.lastPropHash } : {})
|
|
670
786
|
}
|
|
671
787
|
}
|
|
672
788
|
]
|
|
@@ -681,7 +797,20 @@ export const makeChatsSocket = (config) => {
|
|
|
681
797
|
}
|
|
682
798
|
props = reduceBinaryNodeToDictionary(propsNode, 'prop');
|
|
683
799
|
}
|
|
684
|
-
|
|
800
|
+
// Extract protocol-relevant AB props (only the ones we need)
|
|
801
|
+
const privacyTokenProp = props['10518'] ?? props['privacy_token_sending_on_all_1_on_1_messages'];
|
|
802
|
+
if (privacyTokenProp !== undefined) {
|
|
803
|
+
serverProps.privacyTokenOn1to1 = privacyTokenProp === 'true' || privacyTokenProp === '1';
|
|
804
|
+
}
|
|
805
|
+
const profilePicProp = props['9666'] ?? props['profile_scraping_privacy_token_in_photo_iq'];
|
|
806
|
+
if (profilePicProp !== undefined) {
|
|
807
|
+
serverProps.profilePicPrivacyToken = profilePicProp === 'true' || profilePicProp === '1';
|
|
808
|
+
}
|
|
809
|
+
const lidIssueProp = props['14303'] ?? props['lid_trusted_token_issue_to_lid'];
|
|
810
|
+
if (lidIssueProp !== undefined) {
|
|
811
|
+
serverProps.lidTrustedTokenIssueToLid = lidIssueProp === 'true' || lidIssueProp === '1';
|
|
812
|
+
}
|
|
813
|
+
logger.debug({ serverProps }, 'fetched props');
|
|
685
814
|
return props;
|
|
686
815
|
};
|
|
687
816
|
/**
|
|
@@ -821,6 +950,47 @@ export const makeChatsSocket = (config) => {
|
|
|
821
950
|
? shouldSyncHistoryMessage(historyMsg) &&
|
|
822
951
|
PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
|
|
823
952
|
: false;
|
|
953
|
+
if (historyMsg && shouldProcessHistoryMsg) {
|
|
954
|
+
const syncType = historyMsg.syncType;
|
|
955
|
+
// INITIAL_BOOTSTRAP — fire immediately, no progress check (same as WA Web K function)
|
|
956
|
+
if (syncType === proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP &&
|
|
957
|
+
!historySyncStatus.initialBootstrapComplete) {
|
|
958
|
+
historySyncStatus.initialBootstrapComplete = true;
|
|
959
|
+
ev.emit('messaging-history.status', {
|
|
960
|
+
syncType,
|
|
961
|
+
status: 'complete',
|
|
962
|
+
explicit: true
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
// RECENT with progress === 100 — explicit completion
|
|
966
|
+
if (syncType === proto.HistorySync.HistorySyncType.RECENT &&
|
|
967
|
+
historyMsg.progress === 100 &&
|
|
968
|
+
!historySyncStatus.recentSyncComplete) {
|
|
969
|
+
historySyncStatus.recentSyncComplete = true;
|
|
970
|
+
clearTimeout(historySyncPausedTimeout);
|
|
971
|
+
historySyncPausedTimeout = undefined;
|
|
972
|
+
ev.emit('messaging-history.status', {
|
|
973
|
+
syncType,
|
|
974
|
+
status: 'complete',
|
|
975
|
+
explicit: true
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
// Reset 120s paused timeout on any RECENT chunk (like WA Web's handleChunkProgress)
|
|
979
|
+
if (syncType === proto.HistorySync.HistorySyncType.RECENT && !historySyncStatus.recentSyncComplete) {
|
|
980
|
+
clearTimeout(historySyncPausedTimeout);
|
|
981
|
+
historySyncPausedTimeout = setTimeout(() => {
|
|
982
|
+
if (!historySyncStatus.recentSyncComplete) {
|
|
983
|
+
historySyncStatus.recentSyncComplete = true;
|
|
984
|
+
ev.emit('messaging-history.status', {
|
|
985
|
+
syncType: proto.HistorySync.HistorySyncType.RECENT,
|
|
986
|
+
status: 'paused',
|
|
987
|
+
explicit: false
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
historySyncPausedTimeout = undefined;
|
|
991
|
+
}, HISTORY_SYNC_PAUSED_TIMEOUT_MS);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
824
994
|
// State machine: decide on sync and flush
|
|
825
995
|
if (historyMsg && syncState === SyncState.AwaitingInitialSync) {
|
|
826
996
|
if (awaitingSyncTimeout) {
|
|
@@ -840,6 +1010,8 @@ export const makeChatsSocket = (config) => {
|
|
|
840
1010
|
}
|
|
841
1011
|
const doAppStateSync = async () => {
|
|
842
1012
|
if (syncState === SyncState.Syncing) {
|
|
1013
|
+
// All collections will be synced, so clear any blocked ones
|
|
1014
|
+
blockedCollections.clear();
|
|
843
1015
|
logger.info('Doing app state sync');
|
|
844
1016
|
await resyncAppState(ALL_WA_PATCH_NAMES, true);
|
|
845
1017
|
// Sync is complete, go online and flush everything
|
|
@@ -899,6 +1071,11 @@ export const makeChatsSocket = (config) => {
|
|
|
899
1071
|
}
|
|
900
1072
|
});
|
|
901
1073
|
ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
|
|
1074
|
+
if (connection === 'close') {
|
|
1075
|
+
blockedCollections.clear();
|
|
1076
|
+
clearTimeout(historySyncPausedTimeout);
|
|
1077
|
+
historySyncPausedTimeout = undefined;
|
|
1078
|
+
}
|
|
902
1079
|
if (connection === 'open') {
|
|
903
1080
|
if (fireInitQueries) {
|
|
904
1081
|
executeInitQueries().catch(error => onUnexpectedError(error, 'init queries'));
|
|
@@ -908,6 +1085,10 @@ export const makeChatsSocket = (config) => {
|
|
|
908
1085
|
if (!receivedPendingNotifications || syncState !== SyncState.Connecting) {
|
|
909
1086
|
return;
|
|
910
1087
|
}
|
|
1088
|
+
historySyncStatus.initialBootstrapComplete = false;
|
|
1089
|
+
historySyncStatus.recentSyncComplete = false;
|
|
1090
|
+
clearTimeout(historySyncPausedTimeout);
|
|
1091
|
+
historySyncPausedTimeout = undefined;
|
|
911
1092
|
syncState = SyncState.AwaitingInitialSync;
|
|
912
1093
|
logger.info('Connection is now AwaitingInitialSync, buffering events');
|
|
913
1094
|
ev.buffer();
|
|
@@ -920,19 +1101,49 @@ export const makeChatsSocket = (config) => {
|
|
|
920
1101
|
setTimeout(() => ev.flush(), 0);
|
|
921
1102
|
return;
|
|
922
1103
|
}
|
|
923
|
-
|
|
1104
|
+
// On reconnection (accountSyncCounter > 0), the server does not push
|
|
1105
|
+
// history sync notifications — the device already has its data.
|
|
1106
|
+
// Skip the 20s wait and go online immediately.
|
|
1107
|
+
if (authState.creds.accountSyncCounter > 0) {
|
|
1108
|
+
logger.info('Reconnection with existing sync data, skipping history sync wait. Transitioning to Online.');
|
|
1109
|
+
syncState = SyncState.Online;
|
|
1110
|
+
setTimeout(() => ev.flush(), 0);
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
logger.info('First connection, awaiting history sync notification with a 20s timeout.');
|
|
924
1114
|
if (awaitingSyncTimeout) {
|
|
925
1115
|
clearTimeout(awaitingSyncTimeout);
|
|
926
1116
|
}
|
|
927
1117
|
awaitingSyncTimeout = setTimeout(() => {
|
|
928
1118
|
if (syncState === SyncState.AwaitingInitialSync) {
|
|
929
|
-
// TODO: investigate
|
|
930
1119
|
logger.warn('Timeout in AwaitingInitialSync, forcing state to Online and flushing buffer');
|
|
931
1120
|
syncState = SyncState.Online;
|
|
932
1121
|
ev.flush();
|
|
1122
|
+
// Increment so subsequent reconnections skip the 20s wait.
|
|
1123
|
+
// Late-arriving history is still processed via processMessage
|
|
1124
|
+
// regardless of the state machine phase.
|
|
1125
|
+
const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
|
|
1126
|
+
ev.emit('creds.update', { accountSyncCounter });
|
|
933
1127
|
}
|
|
934
1128
|
}, 20000);
|
|
935
1129
|
});
|
|
1130
|
+
// When an app state sync key arrives (myAppStateKeyId is set) and there are
|
|
1131
|
+
// collections blocked on a missing key, trigger a re-sync for just those collections.
|
|
1132
|
+
// This mirrors WA Web's Blocked → retry-on-key-arrival behavior.
|
|
1133
|
+
ev.on('creds.update', ({ myAppStateKeyId }) => {
|
|
1134
|
+
if (!myAppStateKeyId || blockedCollections.size === 0) {
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
// If we're in the middle of a full sync, doAppStateSync handles all collections
|
|
1138
|
+
if (syncState === SyncState.Syncing) {
|
|
1139
|
+
blockedCollections.clear();
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
const collections = [...blockedCollections];
|
|
1143
|
+
blockedCollections.clear();
|
|
1144
|
+
logger.info({ collections }, 'app state sync key arrived, re-syncing blocked collections');
|
|
1145
|
+
resyncAppState(collections, false).catch(error => onUnexpectedError(error, 'blocked collections resync'));
|
|
1146
|
+
});
|
|
936
1147
|
ev.on('lid-mapping.update', async ({ lid, pn }) => {
|
|
937
1148
|
try {
|
|
938
1149
|
await signalRepository.lidMapping.storeLIDPNMappings([{ lid, pn }]);
|
|
@@ -941,18 +1152,13 @@ export const makeChatsSocket = (config) => {
|
|
|
941
1152
|
logger.warn({ lid, pn, error }, 'Failed to store LID-PN mapping');
|
|
942
1153
|
}
|
|
943
1154
|
});
|
|
944
|
-
// Clean up local resources when connection closes
|
|
945
|
-
ev.on('connection.update', ({ connection }) => {
|
|
946
|
-
if (connection === 'close') {
|
|
947
|
-
if (awaitingSyncTimeout) {
|
|
948
|
-
clearTimeout(awaitingSyncTimeout);
|
|
949
|
-
awaitingSyncTimeout = undefined;
|
|
950
|
-
}
|
|
951
|
-
placeholderResendCache.flushAll();
|
|
952
|
-
}
|
|
953
|
-
});
|
|
954
1155
|
return {
|
|
955
1156
|
...sock,
|
|
1157
|
+
serverProps,
|
|
1158
|
+
end: async (error) => {
|
|
1159
|
+
await cleanupInternalResources();
|
|
1160
|
+
await sock.end(error);
|
|
1161
|
+
},
|
|
956
1162
|
createCallLink,
|
|
957
1163
|
getBotListV2,
|
|
958
1164
|
messageMutex,
|