@violetix/baileys 0.5.5 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +1530 -2009
  2. package/WAProto/index.d.ts +14030 -14586
  3. package/WAProto/index.js +58426 -88874
  4. package/lib/Defaults/index.d.ts +2 -7
  5. package/lib/Defaults/index.js +5 -20
  6. package/lib/Signal/Group/sender-key-message.js +19 -1
  7. package/lib/Signal/libsignal.js +82 -29
  8. package/lib/Signal/xeddsa-fast.js +114 -0
  9. package/lib/Socket/Client/types.js +6 -8
  10. package/lib/Socket/Client/websocket.js +3 -38
  11. package/lib/Socket/business.d.ts +0 -3
  12. package/lib/Socket/chats.d.ts +0 -3
  13. package/lib/Socket/chats.js +18 -45
  14. package/lib/Socket/communities.d.ts +0 -3
  15. package/lib/Socket/graphql.js +3 -7
  16. package/lib/Socket/groups.d.ts +0 -3
  17. package/lib/Socket/groups.js +3 -8
  18. package/lib/Socket/index.d.ts +15 -17
  19. package/lib/Socket/messages-recv.d.ts +0 -3
  20. package/lib/Socket/messages-recv.js +43 -127
  21. package/lib/Socket/messages-send.d.ts +0 -4
  22. package/lib/Socket/messages-send.js +63 -191
  23. package/lib/Socket/newsletter.d.ts +0 -3
  24. package/lib/Socket/newsletter.js +1 -2
  25. package/lib/Socket/newsletter.js.map +1 -1
  26. package/lib/Socket/socket.d.ts +0 -9
  27. package/lib/Socket/socket.js +53 -341
  28. package/lib/Store/make-in-memory-store.js +30 -41
  29. package/lib/Types/Auth.d.ts +2 -60
  30. package/lib/Types/Bussines.d.ts +2 -9
  31. package/lib/Types/Call.d.ts +2 -22
  32. package/lib/Types/Chat.d.ts +1 -2
  33. package/lib/Types/Contact.d.ts +2 -11
  34. package/lib/Types/Events.d.ts +2 -41
  35. package/lib/Types/GroupMetadata.d.ts +2 -36
  36. package/lib/Types/Message.d.ts +1 -11
  37. package/lib/Types/Product.d.ts +2 -5
  38. package/lib/Types/Signal.d.ts +2 -10
  39. package/lib/Types/Socket.d.ts +2 -33
  40. package/lib/Types/USync.d.ts +2 -9
  41. package/lib/Types/index.d.ts +1 -3
  42. package/lib/Utils/auth-utils.d.ts +2 -3
  43. package/lib/Utils/auth-utils.js +53 -37
  44. package/lib/Utils/business.js +11 -25
  45. package/lib/Utils/chat-utils.js +4 -6
  46. package/lib/Utils/decode-wa-message.js +2 -2
  47. package/lib/Utils/event-buffer.js +12 -21
  48. package/lib/Utils/generics.d.ts +5 -5
  49. package/lib/Utils/generics.js +7 -25
  50. package/lib/Utils/history.d.ts +1 -2
  51. package/lib/Utils/history.js +83 -137
  52. package/lib/Utils/index.d.ts +0 -4
  53. package/lib/Utils/index.js +0 -4
  54. package/lib/Utils/listener-guard.js +0 -2
  55. package/lib/Utils/message-retry-manager.js +0 -20
  56. package/lib/Utils/messages-media.d.ts +8 -39
  57. package/lib/Utils/messages-media.js +89 -218
  58. package/lib/Utils/messages.d.ts +0 -1
  59. package/lib/Utils/messages.js +36 -122
  60. package/lib/Utils/process-message.d.ts +0 -18
  61. package/lib/Utils/process-message.js +47 -99
  62. package/lib/Utils/rich-message-utils.js +4 -3
  63. package/lib/Utils/use-multi-file-auth-state.d.ts +3 -5
  64. package/lib/Utils/use-multi-file-auth-state.js +6 -27
  65. package/lib/Utils/use-single-file-auth-state.d.ts +1 -1
  66. package/lib/Utils/use-single-file-auth-state.js +3 -12
  67. package/lib/WABinary/types.d.ts +2 -6
  68. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +3 -6
  69. package/lib/WAUSync/Protocols/USyncContactProtocol.js +2 -3
  70. package/lib/WAUSync/USyncQuery.d.ts +1 -1
  71. package/lib/WAUSync/USyncQuery.js +4 -7
  72. package/package.json +107 -123
  73. package/lib/Utils/a2ui.d.ts +0 -50
  74. package/lib/Utils/a2ui.js +0 -168
  75. package/lib/Utils/anchor-guard.d.ts +0 -71
  76. package/lib/Utils/anchor-guard.js +0 -404
  77. package/lib/Utils/connection-manager.d.ts +0 -44
  78. package/lib/Utils/connection-manager.js +0 -258
  79. package/lib/Utils/ignore-key.d.ts +0 -51
  80. package/lib/Utils/ignore-key.js +0 -176
@@ -409,19 +409,15 @@ export const makeGraphQLSocket = sock => {
409
409
  const acquireAccessToken = () => {
410
410
  if (_accessToken) return Promise.resolve(_accessToken)
411
411
  if (_tokenPromise) return _tokenPromise
412
- const pending = (async () => {
412
+ _tokenPromise = (async () => {
413
413
  const nonceData = await sock.wwwGetNonce()
414
414
  const nonce = nonceData?.nonce ?? nonceData
415
415
  const tokenData = await sock.wwwExchangeNonce(nonce)
416
416
  const token = tokenData?.access_token ?? tokenData
417
- if (_tokenPromise === pending) _accessToken = token
417
+ _accessToken = token
418
+ _tokenPromise = null
418
419
  return token
419
420
  })()
420
- _tokenPromise = pending
421
- const clearPending = () => {
422
- if (_tokenPromise === pending) _tokenPromise = null
423
- }
424
- pending.then(clearPending, clearPending)
425
421
  return _tokenPromise
426
422
  }
427
423
 
@@ -253,9 +253,6 @@ export function makeGroupsSocket(config: any): {
253
253
  username: string;
254
254
  jid: any;
255
255
  exists: boolean;
256
- keyRequired: boolean;
257
- isBusiness: boolean;
258
- pnJid: string | undefined;
259
256
  }[]>;
260
257
  fetchUsername: (...jids: any[]) => Promise<{
261
258
  jid: any;
@@ -23,7 +23,7 @@ export const makeGroupsSocket = (config) => {
23
23
  }
24
24
  const promise = groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }])
25
25
  .then(result => extractGroupMetadata(result))
26
- // no swallow: a null here made group sends go to zero recipients silently
26
+ .catch(() => null)
27
27
  .finally(() => inflightGroupMetadata.delete(jid));
28
28
  inflightGroupMetadata.set(jid, promise);
29
29
  return promise;
@@ -69,13 +69,8 @@ export const makeGroupsSocket = (config) => {
69
69
  if (attrs.type !== 'groups') {
70
70
  return;
71
71
  }
72
- try {
73
- await groupFetchAllParticipating();
74
- await sock.cleanDirtyBits('groups');
75
- }
76
- catch (error) {
77
- config.logger?.warn({ error }, 'failed to handle dirty groups');
78
- }
72
+ await groupFetchAllParticipating();
73
+ await sock.cleanDirtyBits('groups');
79
74
  });
80
75
  return {
81
76
  ...sock,
@@ -1,5 +1,5 @@
1
1
  export default makeWASocket;
2
- declare function makeWASocket(config: import('../Types/Socket.js').SocketConfig): {
2
+ declare function makeWASocket(config: any): {
3
3
  /** from ./interop.js */
4
4
  fetchIntegrators: (...args: any[]) => any;
5
5
  acceptInteropTOS: (...args: any[]) => any;
@@ -636,7 +636,6 @@ declare function makeWASocket(config: import('../Types/Socket.js').SocketConfig)
636
636
  updateMemberLabel: (jid: any, memberLabel: any) => Promise<any>;
637
637
  updateMediaMessage: (message: any) => Promise<any>;
638
638
  sendMessage: (jid: any, content: any, options?: {}) => Promise<import("../index.js").proto.WebMessageInfo | undefined>;
639
- groupStatus: (jid: any, content?: any, options?: {}) => Promise<import("../index.js").proto.WebMessageInfo | undefined>;
640
639
  executeWMexQuery: (variables: any, queryId: any, dataPath: any) => Promise<any>;
641
640
  newsletterCreate: (name: any, description: any) => Promise<{
642
641
  id: any;
@@ -863,7 +862,18 @@ declare function makeWASocket(config: import('../Types/Socket.js').SocketConfig)
863
862
  removeQuickReply: (timestamp: any) => Promise<void>;
864
863
  type: string;
865
864
  ws: import("./Client/websocket.js").WebSocketClient;
866
- ev: import('../Types/Events.js').BaileysEventEmitter;
865
+ ev: {
866
+ process(handler: any): () => void;
867
+ emit(event: any, evData: any): any;
868
+ isBuffering(): boolean;
869
+ buffer: () => void;
870
+ flush: () => boolean;
871
+ createBufferedFunction(work: any): (...args: any[]) => Promise<any>;
872
+ on: (...args: any[]) => any;
873
+ off: (...args: any[]) => any;
874
+ removeAllListeners: (...args: any[]) => any;
875
+ destroy(): void;
876
+ };
867
877
  authState: {
868
878
  creds: any;
869
879
  keys: {
@@ -875,15 +885,7 @@ declare function makeWASocket(config: import('../Types/Socket.js').SocketConfig)
875
885
  };
876
886
  signalRepository: any;
877
887
  user: any;
878
- /** true while the transport is repairing itself; do not build a second socket for the account */
879
- isReconnecting: boolean;
880
888
  generateMessageTag: () => string;
881
- /**
882
- * Drops matching inbound stanzas before any handler — including the decryption and
883
- * persistence paths — sees them. The ack is still sent so the server stops re-delivering.
884
- * Returns an unregister function.
885
- */
886
- ignoreKey: (input: import('../Utils/ignore-key.js').WaIgnoreKeyInput) => () => void;
887
889
  query: (node: any, timeoutMs: any) => Promise<any>;
888
890
  waitForMessage: (msgId: any, timeoutMs?: any) => Promise<any>;
889
891
  waitForSocketOpen: () => Promise<void>;
@@ -892,13 +894,12 @@ declare function makeWASocket(config: import('../Types/Socket.js').SocketConfig)
892
894
  logout: (msg: any) => Promise<void>;
893
895
  end: (error: any) => Promise<void>;
894
896
  registerSocketEndHandler: (handler: any) => void;
895
- registerSocketReconnectHandler: (handler: any) => void;
896
897
  onUnexpectedError: (err: any, msg: any) => void;
897
898
  uploadPreKeys: (count?: number) => Promise<void>;
898
899
  uploadPreKeysToServerIfRequired: () => Promise<void>;
899
900
  digestKeyBundle: () => Promise<void>;
900
901
  rotateSignedPreKey: () => Promise<void>;
901
- requestPairingCode: (phoneNumber: string, customPairingCode?: string) => Promise<string>;
902
+ requestPairingCode: (phoneNumber: any, customPairingCode: any) => Promise<any>;
902
903
  updateServerTimeOffset: ({ attrs }: {
903
904
  attrs: any;
904
905
  }) => void;
@@ -916,9 +917,6 @@ declare function makeWASocket(config: import('../Types/Socket.js').SocketConfig)
916
917
  username: string;
917
918
  jid: any;
918
919
  exists: boolean;
919
- keyRequired: boolean;
920
- isBusiness: boolean;
921
- pnJid: string | undefined;
922
920
  }[]>;
923
921
  fetchUsername: (...jids: any[]) => Promise<{
924
922
  jid: any;
@@ -947,4 +945,4 @@ declare function makeWASocket(config: import('../Types/Socket.js').SocketConfig)
947
945
  }>;
948
946
  fetchNewChatMessageCap: () => Promise<any>;
949
947
  };
950
- //# sourceMappingURL=index.d.ts.map
948
+ //# sourceMappingURL=index.d.ts.map
@@ -332,9 +332,6 @@ export function makeMessagesRecvSocket(config: any): {
332
332
  username: string;
333
333
  jid: any;
334
334
  exists: boolean;
335
- keyRequired: boolean;
336
- isBusiness: boolean;
337
- pnJid: string | undefined;
338
335
  }[]>;
339
336
  fetchUsername: (...jids: any[]) => Promise<{
340
337
  jid: any;
@@ -5,7 +5,7 @@ import Long from 'long';
5
5
  import { proto } from '../../WAProto/index.js';
6
6
  import { DEFAULT_CACHE_TTLS, KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT, PLACEHOLDER_MAX_AGE_SECONDS, STATUS_EXPIRY_SECONDS } from '../Defaults/index.js';
7
7
  import { ReachoutTimelockEnforcementType, WAMessageStatus, WAMessageStubType } from '../Types/index.js';
8
- import { ACCOUNT_RESTRICTED_TEXT, aesDecryptCTR, aesEncryptGCM, cleanMessage, Curve, decodeMediaRetryNode, decodeMessageNode, decryptMessageNode, setBotMessageSecret, delay, derivePairingCodeKey, encodeBigEndian, encodeSignedDeviceIdentity, extractAddressingContext, extractE2ESessionFromRetryReceipt, getCallStatusFromNode, getHistoryMsg, getNextPreKeys, getStatusFromReceiptType, handleIdentityChange, hkdf, MISSING_KEYS_ERROR_TEXT, NACK_REASONS, NO_MESSAGE_FOUND_ERROR_TEXT, SERVER_ERROR_CODES, toNumber, unixTimestampSeconds, unpadRandomMax16, xmppPreKey, xmppSignedPreKey } from '../Utils/index.js';
8
+ import { ACCOUNT_RESTRICTED_TEXT, aesDecryptCTR, aesEncryptGCM, cleanMessage, Curve, decodeMediaRetryNode, decodeMessageNode, decryptMessageNode, setBotMessageSecret, delay, derivePairingCodeKey, encodeBigEndian, encodeSignedDeviceIdentity, extractAddressingContext, extractE2ESessionFromRetryReceipt, getCallStatusFromNode, getHistoryMsg, getNextPreKeys, getStatusFromReceiptType, handleIdentityChange, hkdf, MISSING_KEYS_ERROR_TEXT, NACK_REASONS, NO_MESSAGE_FOUND_ERROR_TEXT, SERVER_ERROR_CODES, toNumber, unixTimestampSeconds, xmppPreKey, xmppSignedPreKey } from '../Utils/index.js';
9
9
  import { makeMutex } from '../Utils/make-mutex.js';
10
10
  import { makeOfflineNodeProcessor } from '../Utils/offline-node-processor.js';
11
11
  import { buildAckStanza } from '../Utils/stanza-ack.js';
@@ -20,7 +20,7 @@ function isValidEnforcementType(value) {
20
20
  export const makeMessagesRecvSocket = (config) => {
21
21
  const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid, enableAutoSessionRecreation } = config;
22
22
  const sock = makeMessagesSocket(config);
23
- const { userDevicesCache, devicesMutex, ev, authState, ws, messageMutex, notificationMutex, receiptMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage, messageRetryManager, registerSocketEndHandler, issuePrivacyTokens, fetchAccountReachoutTimelock, placeholderResendCache, fetchPrivacySettings } = sock;
23
+ const { userDevicesCache, devicesMutex, ev, authState, ws, messageMutex, notificationMutex, receiptMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage, messageRetryManager, registerSocketEndHandler, issuePrivacyTokens, fetchAccountReachoutTimelock, placeholderResendCache } = sock;
24
24
  const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
25
25
  /** this mutex ensures that each retryRequest will wait for the previous one to finish */
26
26
  const retryMutex = makeMutex();
@@ -128,34 +128,6 @@ export const makeMessagesRecvSocket = (config) => {
128
128
  case 'MessageCappingInfoNotification':
129
129
  handleMessageCappingNotification(data);
130
130
  break;
131
- case 'UsernameSetNotification': {
132
- const payload = data.xwa2_notify_username_on_change;
133
- if (payload?.lid) {
134
- ev.emit('username.update', { lid: payload.lid, username: payload.username || null, type: 'set' });
135
- }
136
- break;
137
- }
138
- case 'UsernameDeleteNotification': {
139
- const payload = data.xwa2_notify_username_delete;
140
- if (payload?.lid) {
141
- ev.emit('username.update', { lid: payload.lid, username: null, displayName: payload.display_name || null, type: 'delete' });
142
- }
143
- break;
144
- }
145
- case 'LidChangeNotification': {
146
- // a user's LID rotated: carry the PN we knew for the old LID over to the new one
147
- const payload = data.xwa2_notify_lid_change;
148
- const oldLid = payload?.old;
149
- const newLid = payload?.new;
150
- if (oldLid && newLid && isLidUser(newLid)) {
151
- const pn = await signalRepository.lidMapping.getPNForLID(oldLid);
152
- if (pn) {
153
- await signalRepository.lidMapping.storeLIDPNMappings([{ lid: newLid, pn }]);
154
- }
155
- ev.emit('lid-mapping.update', { oldLid, newLid, pn: pn || null });
156
- }
157
- break;
158
- }
159
131
  // newsletter ops still use the legacy <mex> child structure
160
132
  case 'NotificationNewsletterUpdate':
161
133
  case 'NotificationLinkedProfilesUpdates':
@@ -394,7 +366,7 @@ export const makeMessagesRecvSocket = (config) => {
394
366
  }
395
367
  };
396
368
  const sendMessageAck = async (node, errorCode) => {
397
- const stanza = buildAckStanza(node, errorCode, authState.creds.me?.id);
369
+ const stanza = buildAckStanza(node, errorCode, authState.creds.me.id);
398
370
  logger.debug({ recv: { tag: node.tag, attrs: node.attrs }, sent: stanza.attrs }, 'sent ack');
399
371
  await sendNode(stanza);
400
372
  };
@@ -458,6 +430,7 @@ export const makeMessagesRecvSocket = (config) => {
458
430
  if (enableAutoSessionRecreation && messageRetryManager && retryCount > 1) {
459
431
  try {
460
432
  // Check if we have a session with this JID
433
+ const sessionId = signalRepository.jidToSignalProtocolAddress(fromJid);
461
434
  const hasSession = await signalRepository.validateSession(fromJid);
462
435
  const result = messageRetryManager.shouldRecreateSession(fromJid, hasSession.exists);
463
436
  shouldRecreateSession = result.recreate;
@@ -465,7 +438,7 @@ export const makeMessagesRecvSocket = (config) => {
465
438
  if (shouldRecreateSession) {
466
439
  logger.debug({ fromJid, retryCount, reason: recreateReason }, 'recreating session for retry');
467
440
  // Delete existing session to force recreation
468
- await signalRepository.deleteSession([fromJid]);
441
+ await authState.keys.set({ session: { [sessionId]: null } });
469
442
  forceIncludeKeys = true;
470
443
  }
471
444
  }
@@ -657,7 +630,7 @@ export const makeMessagesRecvSocket = (config) => {
657
630
  };
658
631
  break;
659
632
  case 'modify':
660
- const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => JSON.stringify({ id: p.attrs.jid, phoneNumber: p.attrs.phone_number, lid: p.attrs.lid }));
633
+ const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid);
661
634
  msg.messageStubParameters = oldNumber || [];
662
635
  msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
663
636
  break;
@@ -911,42 +884,9 @@ export const makeMessagesRecvSocket = (config) => {
911
884
  ev.emit('blocklist.update', { blocklist, type });
912
885
  }
913
886
  }
914
- else if (child.tag === 'privacy') {
915
- // privacy settings changed on the primary; the notification carries no values,
916
- // so refetch and publish the full set
917
- const settings = await fetchPrivacySettings(true);
918
- ev.emit('privacy.update', settings);
919
- }
920
- break;
921
- case 'passkey_prologue_request':
922
- // The account is passkey-gated (Shortcake): the server will not finish a QR or
923
- // pairing-code link without a WebAuthn assertion from the owner's own authenticator.
924
- // There is no headless completion path, so surface it instead of hanging silently.
925
- logger.warn({ id: node.attrs.id }, 'WhatsApp requires a passkey (Shortcake) to link this account; QR / pairing code cannot complete without the owner authenticator');
926
- ev.emit('connection.update', { passkeyRequired: true });
927
887
  break;
928
888
  case 'link_code_companion_reg':
929
889
  const linkCodeCompanionReg = getBinaryNodeChild(node, 'link_code_companion_reg');
930
- if (linkCodeCompanionReg?.attrs?.stage === 'refresh_code') {
931
- // The server retired the ref behind the code the user is still looking at. Re-run
932
- // companion_hello with the same code so it stays valid; the ref is server-side.
933
- const phone = authState.creds.me?.id ? jidDecode(authState.creds.me.id)?.user : undefined;
934
- if (linkCodeCompanionReg.attrs.force_manual_refresh === 'true' || !phone || !authState.creds.pairingCode) {
935
- logger.warn({ forceManual: linkCodeCompanionReg.attrs.force_manual_refresh }, 'pairing code expired; call requestPairingCode again');
936
- ev.emit('connection.update', { pairingCodeExpired: true });
937
- }
938
- else {
939
- try {
940
- await sock.requestPairingCode(phone, authState.creds.pairingCode);
941
- logger.info('pairing code refreshed with the server; the displayed code is still valid');
942
- }
943
- catch (err) {
944
- logger.warn({ err }, 'failed to refresh pairing code');
945
- ev.emit('connection.update', { pairingCodeExpired: true });
946
- }
947
- }
948
- break;
949
- }
950
890
  const refBuffer = getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_ref');
951
891
  const primaryIdentityPublicKeyBuffer = getBinaryNodeChildBuffer(linkCodeCompanionReg, 'primary_identity_pub');
952
892
  const primaryEphemeralPublicKeyWrappedBuffer = getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub');
@@ -1175,7 +1115,7 @@ export const makeMessagesRecvSocket = (config) => {
1175
1115
  const info = await signalRepository.getSessionInfo(participant);
1176
1116
  if (info && info.registrationId !== 0 && info.registrationId !== receivedRegId) {
1177
1117
  logger.info({ participant, stored: info.registrationId, received: receivedRegId }, 'reg id mismatch on retry without bundle, deleting session');
1178
- await signalRepository.deleteSession([participant]);
1118
+ await authState.keys.set({ session: { [sessionId]: null } });
1179
1119
  }
1180
1120
  }
1181
1121
  }
@@ -1189,7 +1129,7 @@ export const makeMessagesRecvSocket = (config) => {
1189
1129
  else if (retryCount > BASE_KEY_CHECK_RETRY) {
1190
1130
  if (messageRetryManager.hasSameBaseKey(sessionId, msgId, info.baseKey)) {
1191
1131
  logger.warn({ participant, retryCount }, 'base key collision on retry, forcing fresh session');
1192
- await signalRepository.deleteSession([participant]);
1132
+ await authState.keys.set({ session: { [sessionId]: null } });
1193
1133
  }
1194
1134
  messageRetryManager.deleteBaseKey(sessionId, msgId);
1195
1135
  }
@@ -1205,7 +1145,7 @@ export const makeMessagesRecvSocket = (config) => {
1205
1145
  recreateReason = result.reason;
1206
1146
  if (shouldRecreateSession) {
1207
1147
  logger.debug({ participant, retryCount, reason: recreateReason }, 'recreating session for outgoing retry');
1208
- await signalRepository.deleteSession([participant]);
1148
+ await authState.keys.set({ session: { [sessionId]: null } });
1209
1149
  }
1210
1150
  }
1211
1151
  catch (error) {
@@ -1292,6 +1232,7 @@ export const makeMessagesRecvSocket = (config) => {
1292
1232
  if (ids[0] && key.participant && (await willSendMessageAgain(ids[0], key.participant))) {
1293
1233
  if (key.fromMe) {
1294
1234
  try {
1235
+ await updateSendMessageAgainCount(ids[0], key.participant);
1295
1236
  logger.debug({ attrs, key }, 'recv retry request');
1296
1237
  await sendMessagesAgain(key, ids, retryNode, node);
1297
1238
  }
@@ -1314,39 +1255,6 @@ export const makeMessagesRecvSocket = (config) => {
1314
1255
  await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack receipt'));
1315
1256
  }
1316
1257
  };
1317
- /**
1318
- * Server sends none of participant_pn/sender_pn/peer_recipient_pn for senders who have a
1319
- * WhatsApp username set, so the stanza carries no alt JID. Recover it from the local
1320
- * LID->PN store (kept populated by outgoing sends and USync) so consumers keyed by phone
1321
- * number still resolve the sender. No-op when the store has no mapping.
1322
- */
1323
- const recoverAltFromLidStore = async (key) => {
1324
- if (key.participantAlt || key.remoteJidAlt || !key.remoteJid) {
1325
- return;
1326
- }
1327
- const primaryJid = key.participant || key.remoteJid;
1328
- if (!isLidUser(primaryJid)) {
1329
- return;
1330
- }
1331
- try {
1332
- // getPNForLID returns a device-scoped JID; stanza attrs carry it without the device,
1333
- // so normalize to match. jidNormalizedUser yields '' for an undecodable JID.
1334
- const pn = await signalRepository.lidMapping.getPNForLID(primaryJid);
1335
- const pnJid = pn ? jidNormalizedUser(pn) : '';
1336
- if (!pnJid) {
1337
- return;
1338
- }
1339
- if (isJidGroup(key.remoteJid)) {
1340
- key.participantAlt = pnJid;
1341
- }
1342
- else {
1343
- key.remoteJidAlt = pnJid;
1344
- }
1345
- }
1346
- catch (err) {
1347
- logger.debug({ err, primaryJid }, 'failed to recover PN for LID-addressed sender');
1348
- }
1349
- };
1350
1258
  const handleNotification = async (node) => {
1351
1259
  const remoteJid = node.attrs.from;
1352
1260
  try {
@@ -1354,9 +1262,7 @@ export const makeMessagesRecvSocket = (config) => {
1354
1262
  notificationMutex.mutex(async () => {
1355
1263
  const msg = await processNotification(node);
1356
1264
  if (msg) {
1357
- const notifAuthor = node.attrs.participant || remoteJid;
1358
- const fromMe = areJidsSameUser(notifAuthor, authState.creds.me.id) ||
1359
- (!!authState.creds.me.lid && areJidsSameUser(notifAuthor, authState.creds.me.lid));
1265
+ const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me.id);
1360
1266
  const { senderAlt: participantAlt, addressingMode } = extractAddressingContext(node);
1361
1267
  msg.key = {
1362
1268
  remoteJid,
@@ -1368,9 +1274,6 @@ export const makeMessagesRecvSocket = (config) => {
1368
1274
  id: node.attrs.id,
1369
1275
  ...(msg.key || {})
1370
1276
  };
1371
- if (addressingMode === 'lid') {
1372
- await recoverAltFromLidStore(msg.key);
1373
- }
1374
1277
  msg.participant ?? (msg.participant = node.attrs.participant);
1375
1278
  msg.messageTimestamp = +node.attrs.t;
1376
1279
  const fullMsg = proto.WebMessageInfo.fromObject(msg);
@@ -1499,7 +1402,31 @@ export const makeMessagesRecvSocket = (config) => {
1499
1402
  }
1500
1403
  }
1501
1404
  else if (msg.key.addressingMode === 'lid') {
1502
- await recoverAltFromLidStore(msg.key);
1405
+ // Server sent none of participant_pn/sender_pn/peer_recipient_pn — happens for
1406
+ // senders who have a WhatsApp username set — so there's no alt JID in the stanza.
1407
+ // Recover it from the local LID->PN store, which outgoing sends and USync keep
1408
+ // populated, so consumers keyed by phone number still resolve the sender.
1409
+ const primaryJid = msg.key.participant || msg.key.remoteJid;
1410
+ if (isLidUser(primaryJid)) {
1411
+ try {
1412
+ // getPNForLID returns a device-scoped JID; stanza attrs carry it without
1413
+ // the device, so normalize to match. jidNormalizedUser yields '' for an
1414
+ // undecodable JID, so guard before assigning.
1415
+ const pn = await signalRepository.lidMapping.getPNForLID(primaryJid);
1416
+ const pnJid = pn ? jidNormalizedUser(pn) : '';
1417
+ if (pnJid) {
1418
+ if (isJidGroup(msg.key.remoteJid)) {
1419
+ msg.key.participantAlt = pnJid;
1420
+ }
1421
+ else {
1422
+ msg.key.remoteJidAlt = pnJid;
1423
+ }
1424
+ }
1425
+ }
1426
+ catch (err) {
1427
+ logger.debug({ err, primaryJid }, 'failed to recover PN for LID-addressed sender');
1428
+ }
1429
+ }
1503
1430
  }
1504
1431
  await messageMutex.mutex(async () => {
1505
1432
  await decrypt();
@@ -1525,12 +1452,10 @@ export const makeMessagesRecvSocket = (config) => {
1525
1452
  // Message arrived without encryption (e.g. CTWA ads messages).
1526
1453
  // Check if this is eligible for placeholder resend (matching WA Web filters).
1527
1454
  const unavailableNode = getBinaryNodeChild(node, 'unavailable');
1528
- const unavailableType = getBinaryNodeChild(node, 'bot')
1529
- ? 'bot'
1530
- : unavailableNode?.attrs?.hosted === 'true'
1531
- ? 'hosted'
1532
- : unavailableNode?.attrs?.type;
1533
- if (unavailableType === 'bot' || unavailableType === 'hosted' || unavailableType === 'view_once') {
1455
+ const unavailableType = unavailableNode?.attrs?.type;
1456
+ if (unavailableType === 'bot_unavailable_fanout' ||
1457
+ unavailableType === 'hosted_unavailable_fanout' ||
1458
+ unavailableType === 'view_once_unavailable_fanout') {
1534
1459
  logger.debug({ msgId: msg.key.id, unavailableType }, 'skipping placeholder resend for excluded unavailable type');
1535
1460
  acked = true;
1536
1461
  return sendMessageAck(node);
@@ -2094,19 +2019,10 @@ export const makeMessagesRecvSocket = (config) => {
2094
2019
  /* ignore sync errors */
2095
2020
  }
2096
2021
  }
2097
- // Prune expired tctokens once the connection is up, at most once per 24 hours
2022
+ // Prune expired tctokens when coming online, at most once per 24 hours
2098
2023
  // Matches WA Web's CLEAN_TC_TOKENS task
2099
2024
  // Note: don't gate on tcTokenKnownJids.size — the index may still be loading
2100
- //
2101
- // Gated on the CONNECTION, not on presence. `isOnline` is only ever emitted from
2102
- // sendPresenceUpdate (chats.js:638, `isAvailableType = type === 'available'`), and the presence
2103
- // sent on connect is `markOnlineOnConnect ? 'available' : 'unavailable'` (chats.js:1104). So a
2104
- // socket built with `markOnlineOnConnect: false` — the sensible setting for a bot that should
2105
- // not advertise itself, and the usual choice when one host runs many of them — never saw
2106
- // `isOnline` true and therefore never pruned. tcTokenKnownJids only grows (added at :1070 for
2107
- // every new storage jid, persisted to the auth store), and this task was its only cleanup.
2108
- // Presence is a statement to other users; it should not decide whether housekeeping runs.
2109
- if (isOnline || connection === 'open') {
2025
+ if (isOnline) {
2110
2026
  const now = Date.now();
2111
2027
  const DAY_MS = 24 * 60 * 60 * 1000;
2112
2028
  if (now - lastTcTokenPruneTs >= DAY_MS) {
@@ -2196,4 +2112,4 @@ export const makeMessagesRecvSocket = (config) => {
2196
2112
  messageRetryManager
2197
2113
  };
2198
2114
  };
2199
- //# sourceMappingURL=messages-recv.js.map
2115
+ //# sourceMappingURL=messages-recv.js.map
@@ -46,7 +46,6 @@ export function makeMessagesSocket(config: any): {
46
46
  updateMemberLabel: (jid: any, memberLabel: any) => Promise<any>;
47
47
  updateMediaMessage: (message: any) => Promise<any>;
48
48
  sendMessage: (jid: any, content: any, options?: {}) => Promise<proto.WebMessageInfo | undefined>;
49
- groupStatus: (jid: any, content?: any, options?: {}) => Promise<proto.WebMessageInfo | undefined>;
50
49
  executeWMexQuery: (variables: any, queryId: any, dataPath: any) => Promise<any>;
51
50
  newsletterCreate: (name: any, description: any) => Promise<{
52
51
  id: any;
@@ -328,9 +327,6 @@ export function makeMessagesSocket(config: any): {
328
327
  username: string;
329
328
  jid: any;
330
329
  exists: boolean;
331
- keyRequired: boolean;
332
- isBusiness: boolean;
333
- pnJid: string | undefined;
334
330
  }[]>;
335
331
  fetchUsername: (...jids: any[]) => Promise<{
336
332
  jid: any;