@violetix/baileys 0.5.6 → 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.
- package/README.md +1530 -2009
- package/WAProto/index.d.ts +14030 -14586
- package/WAProto/index.js +58426 -88874
- package/lib/Defaults/index.d.ts +2 -7
- package/lib/Defaults/index.js +5 -20
- package/lib/Signal/Group/sender-key-message.js +19 -1
- package/lib/Signal/libsignal.js +82 -29
- package/lib/Signal/xeddsa-fast.js +114 -0
- package/lib/Socket/Client/types.js +6 -8
- package/lib/Socket/Client/websocket.js +3 -38
- package/lib/Socket/business.d.ts +0 -3
- package/lib/Socket/chats.d.ts +0 -3
- package/lib/Socket/chats.js +18 -45
- package/lib/Socket/communities.d.ts +0 -3
- package/lib/Socket/graphql.js +3 -7
- package/lib/Socket/groups.d.ts +0 -3
- package/lib/Socket/groups.js +3 -8
- package/lib/Socket/index.d.ts +15 -17
- package/lib/Socket/messages-recv.d.ts +0 -3
- package/lib/Socket/messages-recv.js +43 -127
- package/lib/Socket/messages-send.d.ts +0 -4
- package/lib/Socket/messages-send.js +63 -191
- package/lib/Socket/newsletter.d.ts +0 -3
- package/lib/Socket/newsletter.js +1 -2
- package/lib/Socket/newsletter.js.map +1 -1
- package/lib/Socket/socket.d.ts +0 -9
- package/lib/Socket/socket.js +53 -346
- package/lib/Store/make-in-memory-store.js +30 -41
- package/lib/Types/Auth.d.ts +2 -60
- package/lib/Types/Bussines.d.ts +2 -9
- package/lib/Types/Call.d.ts +2 -22
- package/lib/Types/Chat.d.ts +1 -2
- package/lib/Types/Contact.d.ts +2 -11
- package/lib/Types/Events.d.ts +2 -41
- package/lib/Types/GroupMetadata.d.ts +2 -36
- package/lib/Types/Message.d.ts +1 -11
- package/lib/Types/Product.d.ts +2 -5
- package/lib/Types/Signal.d.ts +2 -10
- package/lib/Types/Socket.d.ts +2 -33
- package/lib/Types/USync.d.ts +2 -9
- package/lib/Types/index.d.ts +1 -3
- package/lib/Utils/auth-utils.d.ts +2 -3
- package/lib/Utils/auth-utils.js +53 -37
- package/lib/Utils/business.js +11 -25
- package/lib/Utils/chat-utils.js +4 -6
- package/lib/Utils/decode-wa-message.js +2 -2
- package/lib/Utils/event-buffer.js +12 -21
- package/lib/Utils/generics.d.ts +5 -5
- package/lib/Utils/generics.js +7 -25
- package/lib/Utils/history.d.ts +1 -2
- package/lib/Utils/history.js +83 -137
- package/lib/Utils/index.d.ts +0 -4
- package/lib/Utils/index.js +0 -4
- package/lib/Utils/listener-guard.js +0 -2
- package/lib/Utils/message-retry-manager.js +0 -20
- package/lib/Utils/messages-media.d.ts +8 -39
- package/lib/Utils/messages-media.js +89 -218
- package/lib/Utils/messages.d.ts +0 -1
- package/lib/Utils/messages.js +36 -122
- package/lib/Utils/process-message.d.ts +0 -18
- package/lib/Utils/process-message.js +47 -99
- package/lib/Utils/rich-message-utils.js +4 -3
- package/lib/Utils/use-multi-file-auth-state.d.ts +3 -5
- package/lib/Utils/use-multi-file-auth-state.js +6 -27
- package/lib/Utils/use-single-file-auth-state.d.ts +1 -1
- package/lib/Utils/use-single-file-auth-state.js +3 -12
- package/lib/WABinary/types.d.ts +2 -6
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +3 -6
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +2 -3
- package/lib/WAUSync/USyncQuery.d.ts +1 -1
- package/lib/WAUSync/USyncQuery.js +4 -7
- package/package.json +107 -123
- package/lib/Utils/a2ui.d.ts +0 -50
- package/lib/Utils/a2ui.js +0 -168
- package/lib/Utils/anchor-guard.d.ts +0 -71
- package/lib/Utils/anchor-guard.js +0 -404
- package/lib/Utils/connection-manager.d.ts +0 -44
- package/lib/Utils/connection-manager.js +0 -258
- package/lib/Utils/ignore-key.d.ts +0 -51
- package/lib/Utils/ignore-key.js +0 -176
package/lib/Socket/graphql.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
package/lib/Socket/groups.d.ts
CHANGED
|
@@ -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;
|
package/lib/Socket/groups.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
73
|
-
|
|
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,
|
package/lib/Socket/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default makeWASocket;
|
|
2
|
-
declare function makeWASocket(config:
|
|
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:
|
|
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:
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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 =>
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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 =
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
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
|
|
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;
|