@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.
Files changed (139) hide show
  1. package/WAProto/fix-imports.js +22 -18
  2. package/WAProto/index.js +22 -18
  3. package/lib/Defaults/index.d.ts +2 -0
  4. package/lib/Defaults/index.d.ts.map +1 -1
  5. package/lib/Defaults/index.js +3 -1
  6. package/lib/Defaults/index.js.map +1 -1
  7. package/lib/Signal/libsignal.d.ts.map +1 -1
  8. package/lib/Signal/libsignal.js +15 -12
  9. package/lib/Signal/libsignal.js.map +1 -1
  10. package/lib/Signal/lid-mapping.d.ts +3 -5
  11. package/lib/Signal/lid-mapping.d.ts.map +1 -1
  12. package/lib/Signal/lid-mapping.js +37 -22
  13. package/lib/Signal/lid-mapping.js.map +1 -1
  14. package/lib/Socket/Client/websocket.d.ts.map +1 -1
  15. package/lib/Socket/Client/websocket.js +3 -6
  16. package/lib/Socket/Client/websocket.js.map +1 -1
  17. package/lib/Socket/business.d.ts +7 -4
  18. package/lib/Socket/business.d.ts.map +1 -1
  19. package/lib/Socket/chats.d.ts +9 -3
  20. package/lib/Socket/chats.d.ts.map +1 -1
  21. package/lib/Socket/chats.js +253 -47
  22. package/lib/Socket/chats.js.map +1 -1
  23. package/lib/Socket/communities.d.ts +7 -4
  24. package/lib/Socket/communities.d.ts.map +1 -1
  25. package/lib/Socket/groups.d.ts +8 -4
  26. package/lib/Socket/groups.d.ts.map +1 -1
  27. package/lib/Socket/groups.js +20 -0
  28. package/lib/Socket/groups.js.map +1 -1
  29. package/lib/Socket/index.d.ts +7 -4
  30. package/lib/Socket/index.d.ts.map +1 -1
  31. package/lib/Socket/messages-recv.d.ts +7 -4
  32. package/lib/Socket/messages-recv.d.ts.map +1 -1
  33. package/lib/Socket/messages-recv.js +296 -103
  34. package/lib/Socket/messages-recv.js.map +1 -1
  35. package/lib/Socket/messages-send.d.ts +7 -4
  36. package/lib/Socket/messages-send.d.ts.map +1 -1
  37. package/lib/Socket/messages-send.js +113 -50
  38. package/lib/Socket/messages-send.js.map +1 -1
  39. package/lib/Socket/newsletter.d.ts +6 -3
  40. package/lib/Socket/newsletter.d.ts.map +1 -1
  41. package/lib/Socket/newsletter.js +2 -2
  42. package/lib/Socket/newsletter.js.map +1 -1
  43. package/lib/Socket/socket.d.ts +0 -2
  44. package/lib/Socket/socket.d.ts.map +1 -1
  45. package/lib/Socket/socket.js +15 -9
  46. package/lib/Socket/socket.js.map +1 -1
  47. package/lib/Types/Auth.d.ts +2 -0
  48. package/lib/Types/Auth.d.ts.map +1 -1
  49. package/lib/Types/Call.d.ts +1 -1
  50. package/lib/Types/Call.d.ts.map +1 -1
  51. package/lib/Types/Contact.d.ts +2 -0
  52. package/lib/Types/Contact.d.ts.map +1 -1
  53. package/lib/Types/Events.d.ts +16 -0
  54. package/lib/Types/Events.d.ts.map +1 -1
  55. package/lib/Types/GroupMetadata.d.ts +4 -0
  56. package/lib/Types/GroupMetadata.d.ts.map +1 -1
  57. package/lib/Types/Message.d.ts +15 -2
  58. package/lib/Types/Message.d.ts.map +1 -1
  59. package/lib/Types/Message.js.map +1 -1
  60. package/lib/Types/Newsletter.d.ts +4 -2
  61. package/lib/Types/Newsletter.d.ts.map +1 -1
  62. package/lib/Types/Newsletter.js +4 -2
  63. package/lib/Types/Newsletter.js.map +1 -1
  64. package/lib/Types/Signal.d.ts +1 -2
  65. package/lib/Types/Signal.d.ts.map +1 -1
  66. package/lib/Utils/auth-utils.d.ts +5 -0
  67. package/lib/Utils/auth-utils.d.ts.map +1 -1
  68. package/lib/Utils/auth-utils.js +49 -14
  69. package/lib/Utils/auth-utils.js.map +1 -1
  70. package/lib/Utils/chat-utils.d.ts +30 -0
  71. package/lib/Utils/chat-utils.d.ts.map +1 -1
  72. package/lib/Utils/chat-utils.js +34 -8
  73. package/lib/Utils/chat-utils.js.map +1 -1
  74. package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
  75. package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
  76. package/lib/Utils/companion-reg-client-utils.js +41 -0
  77. package/lib/Utils/companion-reg-client-utils.js.map +1 -0
  78. package/lib/Utils/decode-wa-message.d.ts +12 -0
  79. package/lib/Utils/decode-wa-message.d.ts.map +1 -1
  80. package/lib/Utils/decode-wa-message.js +22 -0
  81. package/lib/Utils/decode-wa-message.js.map +1 -1
  82. package/lib/Utils/event-buffer.d.ts +0 -7
  83. package/lib/Utils/event-buffer.d.ts.map +1 -1
  84. package/lib/Utils/event-buffer.js +9 -29
  85. package/lib/Utils/event-buffer.js.map +1 -1
  86. package/lib/Utils/generics.d.ts +1 -0
  87. package/lib/Utils/generics.d.ts.map +1 -1
  88. package/lib/Utils/generics.js +22 -1
  89. package/lib/Utils/generics.js.map +1 -1
  90. package/lib/Utils/history.d.ts.map +1 -1
  91. package/lib/Utils/history.js +11 -9
  92. package/lib/Utils/history.js.map +1 -1
  93. package/lib/Utils/identity-change-handler.d.ts +7 -0
  94. package/lib/Utils/identity-change-handler.d.ts.map +1 -1
  95. package/lib/Utils/identity-change-handler.js +2 -6
  96. package/lib/Utils/identity-change-handler.js.map +1 -1
  97. package/lib/Utils/index.d.ts +15 -15
  98. package/lib/Utils/index.d.ts.map +1 -1
  99. package/lib/Utils/index.js +15 -15
  100. package/lib/Utils/index.js.map +1 -1
  101. package/lib/Utils/message-retry-manager.d.ts +1 -5
  102. package/lib/Utils/message-retry-manager.d.ts.map +1 -1
  103. package/lib/Utils/message-retry-manager.js +7 -14
  104. package/lib/Utils/message-retry-manager.js.map +1 -1
  105. package/lib/Utils/messages-media.js +1 -1
  106. package/lib/Utils/messages-media.js.map +1 -1
  107. package/lib/Utils/messages.d.ts.map +1 -1
  108. package/lib/Utils/messages.js +22 -1
  109. package/lib/Utils/messages.js.map +1 -1
  110. package/lib/Utils/process-message.d.ts.map +1 -1
  111. package/lib/Utils/process-message.js +74 -7
  112. package/lib/Utils/process-message.js.map +1 -1
  113. package/lib/Utils/sync-action-utils.d.ts.map +1 -1
  114. package/lib/Utils/sync-action-utils.js +1 -0
  115. package/lib/Utils/sync-action-utils.js.map +1 -1
  116. package/lib/Utils/tc-token-utils.d.ts +26 -1
  117. package/lib/Utils/tc-token-utils.d.ts.map +1 -1
  118. package/lib/Utils/tc-token-utils.js +149 -4
  119. package/lib/Utils/tc-token-utils.js.map +1 -1
  120. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -1
  121. package/lib/WAUSync/Protocols/USyncContactProtocol.js +26 -3
  122. package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -1
  123. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
  124. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
  125. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
  126. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
  127. package/lib/WAUSync/Protocols/index.d.ts +1 -0
  128. package/lib/WAUSync/Protocols/index.d.ts.map +1 -1
  129. package/lib/WAUSync/Protocols/index.js +1 -0
  130. package/lib/WAUSync/Protocols/index.js.map +1 -1
  131. package/lib/WAUSync/USyncQuery.d.ts +1 -0
  132. package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
  133. package/lib/WAUSync/USyncQuery.js +5 -1
  134. package/lib/WAUSync/USyncQuery.js.map +1 -1
  135. package/lib/WAUSync/USyncUser.d.ts +4 -0
  136. package/lib/WAUSync/USyncUser.d.ts.map +1 -1
  137. package/lib/WAUSync/USyncUser.js +8 -0
  138. package/lib/WAUSync/USyncUser.js.map +1 -1
  139. package/package.json +5 -3
@@ -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
- getPrivacyTokens: (jids: string[]) => Promise<any>;
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsSkpd,CAAC;;;;;;;;;0DApX1qd,GAAG,0BAEV,GACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgXC,CAAA"}
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"}
@@ -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;AAiBrD,OAAO,EACN,KAAK,UAAU,EAOf,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAa,MAAM,YAAY,CAAA;AAIlD,eAAO,MAAM,eAAe,GAAI,QAAQ,YAAY;2BA2lBf,OAAO,GAAG,OAAO,UAAU;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,cAAc,MAAM;;;;;;;;;;;;;;;;;;4BAqHnE,aAAa;+BA/FV,UAAU,UAAU,MAAM;+BA8C1B,MAAM;6BA3FR,MAAM,SAAQ,SAAS,GAAG,OAAO,cAA0B,MAAM;;2BAzYnE,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;2DAshBX,OAAO;+BAvuB7B,kBAAkB;mCAJd,sBAAsB;mCAQtB,cAAc;iCAIhB,oBAAoB;yCAIZ,cAAc;iCAItB,cAAc;uCAIR,mBAAmB;oCAItB,sBAAsB;8CAIZ,MAAM;8BAyMtB,MAAM,KAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;;sBA0fxD,gBAAgB,OAAO,MAAM;2BAxclB,cAAc,GAAG,QAAQ,kBAAkB,MAAM,GAAG,MAAM;4BA2e/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;;;;;;0DAl9BzC,GAAG,0BACD,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmsCP,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"}
@@ -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
- const placeholderResendCache = config.placeholderResendCache ||
32
- new NodeCache({
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
- logger.info(`resyncing ${name} from v${state.version}`);
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 being synced from scratch
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
- if (isIrrecoverableError) {
458
- // stop retrying
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
- const tcTokenContent = await buildTcTokenFromJid({ authState, jid, baseContent });
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: tcTokenContent
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
- const tcTokenContent = await buildTcTokenFromJid({ authState, jid: toJid });
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 || newLTHashState();
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
- /** sending non-abt props may fix QR scan fail if server expects */
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: 'w',
777
+ xmlns: 'abt',
662
778
  type: 'get'
663
779
  },
664
780
  content: [
665
781
  {
666
782
  tag: 'props',
667
783
  attrs: {
668
- protocol: '2',
669
- hash: authState?.creds?.lastPropHash || ''
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
- logger.debug('fetched props');
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
- logger.info('History sync is enabled, awaiting notification with a 20s timeout.');
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,