libzapitu-rf 1.0.0-alpha.2 → 1.0.0-alpha.20
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 +27 -1
- package/WAProto/index.d.ts +3 -0
- package/lib/Defaults/index.d.ts +4 -0
- package/lib/Defaults/index.js +5 -1
- package/lib/Socket/business.d.ts +27 -2
- package/lib/Socket/chats.d.ts +2 -0
- package/lib/Socket/chats.js +4 -38
- package/lib/Socket/groups.d.ts +2 -0
- package/lib/Socket/index.d.ts +27 -2
- package/lib/Socket/messages-recv.d.ts +28 -3
- package/lib/Socket/messages-recv.js +182 -8
- package/lib/Socket/messages-send.d.ts +26 -1
- package/lib/Socket/messages-send.js +247 -40
- package/lib/Socket/mex.d.ts +1 -1
- package/lib/Socket/newsletter.d.ts +4 -3
- package/lib/Socket/newsletter.js +3 -1
- package/lib/Socket/socket.d.ts +3 -0
- package/lib/Socket/socket.js +49 -0
- package/lib/Socket/usync.d.ts +2 -0
- package/lib/Types/Auth.d.ts +8 -0
- package/lib/Types/Events.d.ts +19 -0
- package/lib/Types/Message.d.ts +1 -0
- package/lib/Types/Newsletter.d.ts +6 -2
- package/lib/Types/Newsletter.js +4 -0
- package/lib/Types/State.d.ts +55 -0
- package/lib/Types/State.js +44 -0
- package/lib/Utils/auth-utils.js +1 -1
- package/lib/Utils/cache-utils.d.ts +5 -0
- package/lib/Utils/cache-utils.js +10 -0
- package/lib/Utils/crypto.js +3 -1
- package/lib/Utils/decode-wa-message.d.ts +11 -0
- package/lib/Utils/decode-wa-message.js +33 -10
- package/lib/Utils/event-buffer.js +3 -2
- package/lib/Utils/history.d.ts +3 -2
- package/lib/Utils/history.js +27 -4
- package/lib/Utils/logger.d.ts +2 -1
- package/lib/Utils/messages.js +13 -0
- package/lib/Utils/process-message.d.ts +2 -2
- package/lib/Utils/process-message.js +2 -2
- package/lib/Utils/tc-token-utils.d.ts +53 -0
- package/lib/Utils/tc-token-utils.js +123 -0
- package/lib/Utils/validate-connection.d.ts +2 -2
- package/lib/Utils/validate-connection.js +59 -27
- package/lib/worker/child.d.ts +1 -0
- package/lib/worker/child.js +262 -0
- package/lib/worker/index.d.ts +31 -0
- package/lib/worker/index.js +72 -0
- package/lib/worker/proxy.d.ts +24 -0
- package/lib/worker/proxy.js +510 -0
- package/package.json +24 -4
package/README.md
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
|
+
<h1><img alt="Baileys logo" src="https://raw.githubusercontent.com/zapitu/libzapitu/refs/heads/rf/Media/logo.jpg" height="75"/></h1>
|
|
2
|
+
|
|
1
3
|
# libzapitu-rf
|
|
2
4
|
|
|
3
5
|
LibZapitu is a WebSockets-based TypeScript library for interacting with the WhatsApp Web API.
|
|
4
6
|
|
|
5
7
|
It is forked from [Baileys](https://github.com/WhiskeySockets/Baileys) before the changes to ESM and implements better compatibility to the new privacy of phone numbers from Whatsapp.
|
|
6
8
|
|
|
9
|
+
# To work with libzapitu it is needed:
|
|
10
|
+
|
|
11
|
+
* It is suggested to restart the connections reading again their qrcode
|
|
12
|
+
* Do not use `makeCacheableSignalKeystore` on MakeWASocket
|
|
13
|
+
* Be sure that `getMessage` is implemented and working well
|
|
14
|
+
|
|
15
|
+
# To use libzapitu
|
|
16
|
+
|
|
17
|
+
## To use libzapitu
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
npm install libzapitu-rf
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## To install libzapitu-rf in place of baileys
|
|
24
|
+
|
|
25
|
+
To avoid renaming imports from baileys on your existing code you can use npm aliasing function.
|
|
26
|
+
|
|
27
|
+
Example: if your code uses "baileys" on imports:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
npm install baileys@npm:libzapitu-rf
|
|
31
|
+
```
|
|
32
|
+
|
|
7
33
|
# Sponsor the author
|
|
8
34
|
|
|
9
35
|
Work on this fork is mostly from [Renato Freitas](https://github.com/renatoiub)
|
|
@@ -180,7 +206,7 @@ WhatsApp provides a multi-device API that allows Baileys to be authenticated as
|
|
|
180
206
|
> You can customize browser name if you connect with **QR-CODE**, with `Browser` constant, we have some browsers config, **see [here](https://baileys.whiskeysockets.io/types/BrowsersMap.html)**
|
|
181
207
|
|
|
182
208
|
```ts
|
|
183
|
-
import makeWASocket from '
|
|
209
|
+
import makeWASocket from 'libzapitu-rf'
|
|
184
210
|
|
|
185
211
|
const sock = makeWASocket({
|
|
186
212
|
// can provide additional config here
|
package/WAProto/index.d.ts
CHANGED
|
@@ -52837,6 +52837,9 @@ export namespace proto {
|
|
|
52837
52837
|
|
|
52838
52838
|
/** WebMessageInfo botTargetId */
|
|
52839
52839
|
botTargetId?: (string|null);
|
|
52840
|
+
|
|
52841
|
+
/** view once message */
|
|
52842
|
+
viewOnce?: (boolean|null);
|
|
52840
52843
|
}
|
|
52841
52844
|
|
|
52842
52845
|
/** Represents a WebMessageInfo. */
|
package/lib/Defaults/index.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ export declare const DEFAULT_ORIGIN = "https://web.whatsapp.com";
|
|
|
5
5
|
export declare const DEF_CALLBACK_PREFIX = "CB:";
|
|
6
6
|
export declare const DEF_TAG_PREFIX = "TAG:";
|
|
7
7
|
export declare const PHONE_CONNECTION_CB = "CB:Pong";
|
|
8
|
+
export declare const WA_ADV_ACCOUNT_SIG_PREFIX: Buffer<ArrayBuffer>;
|
|
9
|
+
export declare const WA_ADV_DEVICE_SIG_PREFIX: Buffer<ArrayBuffer>;
|
|
10
|
+
export declare const WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX: Buffer<ArrayBuffer>;
|
|
11
|
+
export declare const WA_ADV_HOSTED_DEVICE_SIG_PREFIX: Buffer<ArrayBuffer>;
|
|
8
12
|
export declare const WA_DEFAULT_EPHEMERAL: number;
|
|
9
13
|
export declare const NOISE_MODE = "Noise_XX_25519_AESGCM_SHA256\0\0\0\0";
|
|
10
14
|
export declare const DICT_VERSION = 3;
|
package/lib/Defaults/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.DEFAULT_CACHE_TTLS = exports.INITIAL_PREKEY_COUNT = exports.MIN_PREKEY_COUNT = exports.MEDIA_KEYS = exports.MEDIA_HKDF_KEY_MAPPING = exports.MEDIA_PATH_MAP = exports.DEFAULT_CONNECTION_CONFIG = exports.PROCESSABLE_HISTORY_TYPES = exports.WA_CERT_DETAILS = exports.URL_REGEX = exports.NOISE_WA_HEADER = exports.KEY_BUNDLE_TYPE = exports.DICT_VERSION = exports.NOISE_MODE = exports.WA_DEFAULT_EPHEMERAL = exports.PHONE_CONNECTION_CB = exports.DEF_TAG_PREFIX = exports.DEF_CALLBACK_PREFIX = exports.DEFAULT_ORIGIN = exports.UNAUTHORIZED_CODES = void 0;
|
|
6
|
+
exports.DEFAULT_CACHE_TTLS = exports.INITIAL_PREKEY_COUNT = exports.MIN_PREKEY_COUNT = exports.MEDIA_KEYS = exports.MEDIA_HKDF_KEY_MAPPING = exports.MEDIA_PATH_MAP = exports.DEFAULT_CONNECTION_CONFIG = exports.PROCESSABLE_HISTORY_TYPES = exports.WA_CERT_DETAILS = exports.URL_REGEX = exports.NOISE_WA_HEADER = exports.KEY_BUNDLE_TYPE = exports.DICT_VERSION = exports.NOISE_MODE = exports.WA_DEFAULT_EPHEMERAL = exports.WA_ADV_HOSTED_DEVICE_SIG_PREFIX = exports.WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX = exports.WA_ADV_DEVICE_SIG_PREFIX = exports.WA_ADV_ACCOUNT_SIG_PREFIX = exports.PHONE_CONNECTION_CB = exports.DEF_TAG_PREFIX = exports.DEF_CALLBACK_PREFIX = exports.DEFAULT_ORIGIN = exports.UNAUTHORIZED_CODES = void 0;
|
|
7
7
|
const WAProto_1 = require("../../WAProto");
|
|
8
8
|
const libsignal_1 = require("../Signal/libsignal");
|
|
9
9
|
const Utils_1 = require("../Utils");
|
|
@@ -14,6 +14,10 @@ exports.DEFAULT_ORIGIN = 'https://web.whatsapp.com';
|
|
|
14
14
|
exports.DEF_CALLBACK_PREFIX = 'CB:';
|
|
15
15
|
exports.DEF_TAG_PREFIX = 'TAG:';
|
|
16
16
|
exports.PHONE_CONNECTION_CB = 'CB:Pong';
|
|
17
|
+
exports.WA_ADV_ACCOUNT_SIG_PREFIX = Buffer.from([6, 0]);
|
|
18
|
+
exports.WA_ADV_DEVICE_SIG_PREFIX = Buffer.from([6, 1]);
|
|
19
|
+
exports.WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX = Buffer.from([6, 5]);
|
|
20
|
+
exports.WA_ADV_HOSTED_DEVICE_SIG_PREFIX = Buffer.from([6, 6]);
|
|
17
21
|
exports.WA_DEFAULT_EPHEMERAL = 7 * 24 * 60 * 60;
|
|
18
22
|
exports.NOISE_MODE = 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0';
|
|
19
23
|
exports.DICT_VERSION = 3;
|
package/lib/Socket/business.d.ts
CHANGED
|
@@ -18,9 +18,11 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
18
18
|
sendMessageAck: ({ tag, attrs, content }: BinaryNode, errorCode?: number) => Promise<void>;
|
|
19
19
|
sendRetryRequest: (node: BinaryNode, forceIncludeKeys?: boolean) => Promise<void>;
|
|
20
20
|
rejectCall: (callId: string, callFrom: string) => Promise<void>;
|
|
21
|
-
fetchMessageHistory: (count: number, oldestMsgKey: import("../Types").WAMessageKey, oldestMsgTimestamp: number |
|
|
21
|
+
fetchMessageHistory: (count: number, oldestMsgKey: import("../Types").WAMessageKey, oldestMsgTimestamp: number | Long) => Promise<string>;
|
|
22
|
+
fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>;
|
|
23
|
+
fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>;
|
|
22
24
|
requestPlaceholderResend: (messageKey: import("../Types").WAMessageKey) => Promise<string | undefined>;
|
|
23
|
-
getPrivacyTokens: (jids: string[]) => Promise<any>;
|
|
25
|
+
getPrivacyTokens: (jids: string[], timestamp?: number) => Promise<any>;
|
|
24
26
|
assertSessions: (jids: string[], force: boolean, lids?: string) => Promise<boolean>;
|
|
25
27
|
relayMessage: (jid: string, message: import("../Types").WAProto.IMessage, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, isretry }: import("../Types").MessageRelayOptions) => Promise<string>;
|
|
26
28
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: import("../Types").MessageReceiptType) => Promise<void>;
|
|
@@ -39,6 +41,29 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
|
|
|
39
41
|
getUSyncDevices: (jids: string[], useCache: boolean, ignoreZeroDevices: boolean) => Promise<import("../WABinary").JidWithDevice[]>;
|
|
40
42
|
updateMediaMessage: (message: import("../Types").WAProto.IWebMessageInfo) => Promise<import("../Types").WAProto.IWebMessageInfo>;
|
|
41
43
|
sendMessage: (jid: string, content: import("../Types").AnyMessageContent, options?: import("../Types").MiscMessageGenerationOptions) => Promise<import("../Types").WAProto.WebMessageInfo | undefined>;
|
|
44
|
+
newsletterCreate: (name: string, description?: string) => Promise<import("../Types").NewsletterMetadata>;
|
|
45
|
+
newsletterUpdate: (jid: string, updates: import("../Types").NewsletterUpdate) => Promise<unknown>;
|
|
46
|
+
newsletterSubscribers: (jid: string) => Promise<{
|
|
47
|
+
subscribers: number;
|
|
48
|
+
}>;
|
|
49
|
+
newsletterMetadata: (type: "invite" | "jid", key: string) => Promise<import("../Types").NewsletterMetadata | null>;
|
|
50
|
+
newsletterFollow: (jid: string) => Promise<unknown>;
|
|
51
|
+
newsletterUnfollow: (jid: string) => Promise<unknown>;
|
|
52
|
+
newsletterMute: (jid: string) => Promise<unknown>;
|
|
53
|
+
newsletterUnmute: (jid: string) => Promise<unknown>;
|
|
54
|
+
newsletterUpdateName: (jid: string, name: string) => Promise<unknown>;
|
|
55
|
+
newsletterUpdateDescription: (jid: string, description: string) => Promise<unknown>;
|
|
56
|
+
newsletterUpdatePicture: (jid: string, content: import("../Types").WAMediaUpload) => Promise<unknown>;
|
|
57
|
+
newsletterRemovePicture: (jid: string) => Promise<unknown>;
|
|
58
|
+
newsletterReactMessage: (jid: string, serverId: string, reaction?: string) => Promise<void>;
|
|
59
|
+
newsletterFetchMessages: (jid: string, count: number, since: number, after: number) => Promise<any>;
|
|
60
|
+
subscribeNewsletterUpdates: (jid: string) => Promise<{
|
|
61
|
+
duration: string;
|
|
62
|
+
} | null>;
|
|
63
|
+
newsletterAdminCount: (jid: string) => Promise<number>;
|
|
64
|
+
newsletterChangeOwner: (jid: string, newOwnerJid: string) => Promise<void>;
|
|
65
|
+
newsletterDemote: (jid: string, userJid: string) => Promise<void>;
|
|
66
|
+
newsletterDelete: (jid: string) => Promise<void>;
|
|
42
67
|
groupMetadata: (jid: string) => Promise<import("../Types").GroupMetadata>;
|
|
43
68
|
groupCreate: (subject: string, participants: string[]) => Promise<import("../Types").GroupMetadata>;
|
|
44
69
|
groupLeave: (id: string) => Promise<void>;
|
package/lib/Socket/chats.d.ts
CHANGED
|
@@ -85,6 +85,8 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
85
85
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
86
86
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
87
87
|
requestPairingCode: (phoneNumber: string, customPairingCode?: string) => Promise<string>;
|
|
88
|
+
fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>;
|
|
89
|
+
fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>;
|
|
88
90
|
waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => Promise<boolean | undefined>, timeoutMs?: number) => Promise<void>;
|
|
89
91
|
sendWAMBuffer: (wamBuffer: Buffer) => Promise<any>;
|
|
90
92
|
};
|
package/lib/Socket/chats.js
CHANGED
|
@@ -537,38 +537,6 @@ const makeChatsSocket = (config) => {
|
|
|
537
537
|
]
|
|
538
538
|
: undefined
|
|
539
539
|
});
|
|
540
|
-
const handlePresenceUpdate = ({ tag, attrs, content }) => {
|
|
541
|
-
var _a;
|
|
542
|
-
let presence;
|
|
543
|
-
const jid = attrs.from;
|
|
544
|
-
const participant = attrs.participant || attrs.from;
|
|
545
|
-
if (shouldIgnoreJid(jid) && jid !== '@s.whatsapp.net') {
|
|
546
|
-
return;
|
|
547
|
-
}
|
|
548
|
-
if (tag === 'presence') {
|
|
549
|
-
presence = {
|
|
550
|
-
lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
|
|
551
|
-
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
else if (Array.isArray(content)) {
|
|
555
|
-
const [firstChild] = content;
|
|
556
|
-
let type = firstChild.tag;
|
|
557
|
-
if (type === 'paused') {
|
|
558
|
-
type = 'available';
|
|
559
|
-
}
|
|
560
|
-
if (((_a = firstChild.attrs) === null || _a === void 0 ? void 0 : _a.media) === 'audio') {
|
|
561
|
-
type = 'recording';
|
|
562
|
-
}
|
|
563
|
-
presence = { lastKnownPresence: type };
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
logger.error({ tag, attrs, content }, 'recv invalid presence node');
|
|
567
|
-
}
|
|
568
|
-
if (presence) {
|
|
569
|
-
ev.emit('presence.update', { id: jid, presences: { [participant]: presence } });
|
|
570
|
-
}
|
|
571
|
-
};
|
|
572
540
|
const appPatch = async (patchCreate) => {
|
|
573
541
|
const name = patchCreate.type;
|
|
574
542
|
const myAppStateKeyId = authState.creds.myAppStateKeyId;
|
|
@@ -635,15 +603,15 @@ const makeChatsSocket = (config) => {
|
|
|
635
603
|
tag: 'iq',
|
|
636
604
|
attrs: {
|
|
637
605
|
to: WABinary_1.S_WHATSAPP_NET,
|
|
638
|
-
xmlns: '
|
|
606
|
+
xmlns: 'abt',
|
|
639
607
|
type: 'get'
|
|
640
608
|
},
|
|
641
609
|
content: [
|
|
642
610
|
{
|
|
643
611
|
tag: 'props',
|
|
644
612
|
attrs: {
|
|
645
|
-
protocol: '
|
|
646
|
-
|
|
613
|
+
protocol: '1',
|
|
614
|
+
...(((_a = authState === null || authState === void 0 ? void 0 : authState.creds) === null || _a === void 0 ? void 0 : _a.lastPropHash) ? { hash: authState.creds.lastPropHash } : {})
|
|
647
615
|
}
|
|
648
616
|
}
|
|
649
617
|
]
|
|
@@ -793,7 +761,7 @@ const makeChatsSocket = (config) => {
|
|
|
793
761
|
keyStore: authState.keys,
|
|
794
762
|
logger,
|
|
795
763
|
options: config.options
|
|
796
|
-
})
|
|
764
|
+
}, authState)
|
|
797
765
|
]);
|
|
798
766
|
if (((_c = (_b = msg.message) === null || _b === void 0 ? void 0 : _b.protocolMessage) === null || _c === void 0 ? void 0 : _c.appStateSyncKeyShare) && pendingAppStateSync) {
|
|
799
767
|
await doAppStateSync();
|
|
@@ -812,8 +780,6 @@ const makeChatsSocket = (config) => {
|
|
|
812
780
|
}
|
|
813
781
|
}
|
|
814
782
|
});
|
|
815
|
-
ws.on('CB:presence', handlePresenceUpdate);
|
|
816
|
-
ws.on('CB:chatstate', handlePresenceUpdate);
|
|
817
783
|
ws.on('CB:ib,,dirty', async (node) => {
|
|
818
784
|
const { attrs } = (0, WABinary_1.getBinaryNodeChild)(node, 'dirty');
|
|
819
785
|
const type = attrs.type;
|
package/lib/Socket/groups.d.ts
CHANGED
|
@@ -125,6 +125,8 @@ export declare const makeGroupsSocket: (config: SocketConfig) => {
|
|
|
125
125
|
uploadPreKeys: (count?: number) => Promise<void>;
|
|
126
126
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
127
127
|
requestPairingCode: (phoneNumber: string, customPairingCode?: string) => Promise<string>;
|
|
128
|
+
fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>;
|
|
129
|
+
fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>;
|
|
128
130
|
waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => Promise<boolean | undefined>, timeoutMs?: number) => Promise<void>;
|
|
129
131
|
sendWAMBuffer: (wamBuffer: Buffer) => Promise<any>;
|
|
130
132
|
};
|
package/lib/Socket/index.d.ts
CHANGED
|
@@ -17,9 +17,11 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
17
17
|
sendMessageAck: ({ tag, attrs, content }: import("..").BinaryNode, errorCode?: number) => Promise<void>;
|
|
18
18
|
sendRetryRequest: (node: import("..").BinaryNode, forceIncludeKeys?: boolean) => Promise<void>;
|
|
19
19
|
rejectCall: (callId: string, callFrom: string) => Promise<void>;
|
|
20
|
-
fetchMessageHistory: (count: number, oldestMsgKey: import("../Types").WAMessageKey, oldestMsgTimestamp: number |
|
|
20
|
+
fetchMessageHistory: (count: number, oldestMsgKey: import("../Types").WAMessageKey, oldestMsgTimestamp: number | Long) => Promise<string>;
|
|
21
|
+
fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>;
|
|
22
|
+
fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>;
|
|
21
23
|
requestPlaceholderResend: (messageKey: import("../Types").WAMessageKey) => Promise<string | undefined>;
|
|
22
|
-
getPrivacyTokens: (jids: string[]) => Promise<any>;
|
|
24
|
+
getPrivacyTokens: (jids: string[], timestamp?: number) => Promise<any>;
|
|
23
25
|
assertSessions: (jids: string[], force: boolean, lids?: string) => Promise<boolean>;
|
|
24
26
|
relayMessage: (jid: string, message: import("../Types").WAProto.IMessage, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, isretry }: import("../Types").MessageRelayOptions) => Promise<string>;
|
|
25
27
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: import("../Types").MessageReceiptType) => Promise<void>;
|
|
@@ -38,6 +40,29 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
|
|
|
38
40
|
getUSyncDevices: (jids: string[], useCache: boolean, ignoreZeroDevices: boolean) => Promise<import("..").JidWithDevice[]>;
|
|
39
41
|
updateMediaMessage: (message: import("../Types").WAProto.IWebMessageInfo) => Promise<import("../Types").WAProto.IWebMessageInfo>;
|
|
40
42
|
sendMessage: (jid: string, content: import("../Types").AnyMessageContent, options?: import("../Types").MiscMessageGenerationOptions) => Promise<import("../Types").WAProto.WebMessageInfo | undefined>;
|
|
43
|
+
newsletterCreate: (name: string, description?: string) => Promise<import("../Types").NewsletterMetadata>;
|
|
44
|
+
newsletterUpdate: (jid: string, updates: import("../Types").NewsletterUpdate) => Promise<unknown>;
|
|
45
|
+
newsletterSubscribers: (jid: string) => Promise<{
|
|
46
|
+
subscribers: number;
|
|
47
|
+
}>;
|
|
48
|
+
newsletterMetadata: (type: "invite" | "jid", key: string) => Promise<import("../Types").NewsletterMetadata | null>;
|
|
49
|
+
newsletterFollow: (jid: string) => Promise<unknown>;
|
|
50
|
+
newsletterUnfollow: (jid: string) => Promise<unknown>;
|
|
51
|
+
newsletterMute: (jid: string) => Promise<unknown>;
|
|
52
|
+
newsletterUnmute: (jid: string) => Promise<unknown>;
|
|
53
|
+
newsletterUpdateName: (jid: string, name: string) => Promise<unknown>;
|
|
54
|
+
newsletterUpdateDescription: (jid: string, description: string) => Promise<unknown>;
|
|
55
|
+
newsletterUpdatePicture: (jid: string, content: import("../Types").WAMediaUpload) => Promise<unknown>;
|
|
56
|
+
newsletterRemovePicture: (jid: string) => Promise<unknown>;
|
|
57
|
+
newsletterReactMessage: (jid: string, serverId: string, reaction?: string) => Promise<void>;
|
|
58
|
+
newsletterFetchMessages: (jid: string, count: number, since: number, after: number) => Promise<any>;
|
|
59
|
+
subscribeNewsletterUpdates: (jid: string) => Promise<{
|
|
60
|
+
duration: string;
|
|
61
|
+
} | null>;
|
|
62
|
+
newsletterAdminCount: (jid: string) => Promise<number>;
|
|
63
|
+
newsletterChangeOwner: (jid: string, newOwnerJid: string) => Promise<void>;
|
|
64
|
+
newsletterDemote: (jid: string, userJid: string) => Promise<void>;
|
|
65
|
+
newsletterDelete: (jid: string) => Promise<void>;
|
|
41
66
|
groupMetadata: (jid: string) => Promise<import("../Types").GroupMetadata>;
|
|
42
67
|
groupCreate: (subject: string, participants: string[]) => Promise<import("../Types").GroupMetadata>;
|
|
43
68
|
groupLeave: (id: string) => Promise<void>;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
2
|
import Long = require('long');
|
|
3
3
|
import { proto } from '../../WAProto';
|
|
4
|
-
import { MessageReceiptType, MessageRelayOptions, SocketConfig, WAMessageKey } from '../Types';
|
|
4
|
+
import { MessageReceiptType, MessageRelayOptions, SocketConfig, WAMessageKey, WAPresence } from '../Types';
|
|
5
5
|
import { BinaryNode } from '../WABinary';
|
|
6
6
|
export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
|
|
7
7
|
sendMessageAck: ({ tag, attrs, content }: BinaryNode, errorCode?: number) => Promise<void>;
|
|
8
8
|
sendRetryRequest: (node: BinaryNode, forceIncludeKeys?: boolean) => Promise<void>;
|
|
9
9
|
rejectCall: (callId: string, callFrom: string) => Promise<void>;
|
|
10
10
|
fetchMessageHistory: (count: number, oldestMsgKey: WAMessageKey, oldestMsgTimestamp: number | Long) => Promise<string>;
|
|
11
|
+
fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>;
|
|
12
|
+
fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>;
|
|
11
13
|
requestPlaceholderResend: (messageKey: WAMessageKey) => Promise<string | undefined>;
|
|
12
|
-
getPrivacyTokens: (jids: string[]) => Promise<any>;
|
|
14
|
+
getPrivacyTokens: (jids: string[], timestamp?: number) => Promise<any>;
|
|
13
15
|
assertSessions: (jids: string[], force: boolean, lids?: string) => Promise<boolean>;
|
|
14
16
|
relayMessage: (jid: string, message: proto.IMessage, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, isretry }: MessageRelayOptions) => Promise<string>;
|
|
15
17
|
sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: MessageReceiptType) => Promise<void>;
|
|
@@ -28,6 +30,29 @@ export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
|
|
|
28
30
|
getUSyncDevices: (jids: string[], useCache: boolean, ignoreZeroDevices: boolean) => Promise<import("../WABinary").JidWithDevice[]>;
|
|
29
31
|
updateMediaMessage: (message: proto.IWebMessageInfo) => Promise<proto.IWebMessageInfo>;
|
|
30
32
|
sendMessage: (jid: string, content: import("../Types").AnyMessageContent, options?: import("../Types").MiscMessageGenerationOptions) => Promise<proto.WebMessageInfo | undefined>;
|
|
33
|
+
newsletterCreate: (name: string, description?: string) => Promise<import("../Types").NewsletterMetadata>;
|
|
34
|
+
newsletterUpdate: (jid: string, updates: import("../Types").NewsletterUpdate) => Promise<unknown>;
|
|
35
|
+
newsletterSubscribers: (jid: string) => Promise<{
|
|
36
|
+
subscribers: number;
|
|
37
|
+
}>;
|
|
38
|
+
newsletterMetadata: (type: "invite" | "jid", key: string) => Promise<import("../Types").NewsletterMetadata | null>;
|
|
39
|
+
newsletterFollow: (jid: string) => Promise<unknown>;
|
|
40
|
+
newsletterUnfollow: (jid: string) => Promise<unknown>;
|
|
41
|
+
newsletterMute: (jid: string) => Promise<unknown>;
|
|
42
|
+
newsletterUnmute: (jid: string) => Promise<unknown>;
|
|
43
|
+
newsletterUpdateName: (jid: string, name: string) => Promise<unknown>;
|
|
44
|
+
newsletterUpdateDescription: (jid: string, description: string) => Promise<unknown>;
|
|
45
|
+
newsletterUpdatePicture: (jid: string, content: import("../Types").WAMediaUpload) => Promise<unknown>;
|
|
46
|
+
newsletterRemovePicture: (jid: string) => Promise<unknown>;
|
|
47
|
+
newsletterReactMessage: (jid: string, serverId: string, reaction?: string) => Promise<void>;
|
|
48
|
+
newsletterFetchMessages: (jid: string, count: number, since: number, after: number) => Promise<any>;
|
|
49
|
+
subscribeNewsletterUpdates: (jid: string) => Promise<{
|
|
50
|
+
duration: string;
|
|
51
|
+
} | null>;
|
|
52
|
+
newsletterAdminCount: (jid: string) => Promise<number>;
|
|
53
|
+
newsletterChangeOwner: (jid: string, newOwnerJid: string) => Promise<void>;
|
|
54
|
+
newsletterDemote: (jid: string, userJid: string) => Promise<void>;
|
|
55
|
+
newsletterDelete: (jid: string) => Promise<void>;
|
|
31
56
|
groupMetadata: (jid: string) => Promise<import("../Types").GroupMetadata>;
|
|
32
57
|
groupCreate: (subject: string, participants: string[]) => Promise<import("../Types").GroupMetadata>;
|
|
33
58
|
groupLeave: (id: string) => Promise<void>;
|
|
@@ -66,7 +91,7 @@ export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
|
|
|
66
91
|
};
|
|
67
92
|
upsertMessage: (msg: import("../Types").WAMessage, type: import("../Types").MessageUpsertType) => Promise<void>;
|
|
68
93
|
appPatch: (patchCreate: import("../Types").WAPatchCreate) => Promise<void>;
|
|
69
|
-
sendPresenceUpdate: (type:
|
|
94
|
+
sendPresenceUpdate: (type: WAPresence, toJid?: string) => Promise<void>;
|
|
70
95
|
presenceSubscribe: (toJid: string, tcToken?: Buffer) => Promise<void>;
|
|
71
96
|
profilePictureUrl: (jid: string, type?: "preview" | "image", timeoutMs?: number) => Promise<string | undefined>;
|
|
72
97
|
onWhatsApp: (...jids: string[]) => Promise<{
|
|
@@ -18,7 +18,7 @@ const messages_send_1 = require("./messages-send");
|
|
|
18
18
|
const makeMessagesRecvSocket = (config) => {
|
|
19
19
|
const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid } = config;
|
|
20
20
|
const sock = (0, messages_send_1.makeMessagesSocket)(config);
|
|
21
|
-
const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage } = sock;
|
|
21
|
+
const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage, fetchAccountReachoutTimelock, fetchNewChatMessageCap } = sock;
|
|
22
22
|
/** this mutex ensures that each retryRequest will wait for the previous one to finish */
|
|
23
23
|
const retryMutex = (0, make_mutex_1.makeMutex)();
|
|
24
24
|
const msgRetryCache = config.msgRetryCounterCache ||
|
|
@@ -87,7 +87,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
87
87
|
await query(stanza);
|
|
88
88
|
};
|
|
89
89
|
const sendRetryRequest = async (node, forceIncludeKeys = false) => {
|
|
90
|
-
const { fullMessage } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '');
|
|
90
|
+
const { fullMessage, author } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '');
|
|
91
91
|
const { key: msgKey } = fullMessage;
|
|
92
92
|
const msgId = msgKey.id;
|
|
93
93
|
const key = `${msgId}:${msgKey === null || msgKey === void 0 ? void 0 : msgKey.participant}`;
|
|
@@ -138,7 +138,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
138
138
|
if (node.attrs.participant) {
|
|
139
139
|
receipt.attrs.participant = node.attrs.participant;
|
|
140
140
|
}
|
|
141
|
-
if (retryCount
|
|
141
|
+
if (retryCount <= 2 && forceIncludeKeys) {
|
|
142
|
+
await assertSessions([(0, WABinary_1.jidNormalizedUser)(author)], true);
|
|
142
143
|
const { update, preKeys } = await (0, Utils_1.getNextPreKeys)(authState, 1);
|
|
143
144
|
const [keyId] = Object.keys(preKeys);
|
|
144
145
|
const key = preKeys[+keyId];
|
|
@@ -293,6 +294,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
293
294
|
const from = (0, WABinary_1.jidNormalizedUser)(node.attrs.from);
|
|
294
295
|
switch (nodeType) {
|
|
295
296
|
case 'privacy_token':
|
|
297
|
+
await handlePrivacyTokenNotification(node);
|
|
296
298
|
const tokenList = (0, WABinary_1.getBinaryNodeChildren)(child, 'token');
|
|
297
299
|
for (const { attrs, content } of tokenList) {
|
|
298
300
|
const jid = attrs.jid;
|
|
@@ -442,6 +444,32 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
442
444
|
});
|
|
443
445
|
authState.creds.registered = true;
|
|
444
446
|
ev.emit('creds.update', authState.creds);
|
|
447
|
+
break;
|
|
448
|
+
case 'passkey_prologue_request': {
|
|
449
|
+
const optsNode = (0, WABinary_1.getBinaryNodeChild)(node, 'passkey_request_options');
|
|
450
|
+
let publicKey;
|
|
451
|
+
const content = optsNode === null || optsNode === void 0 ? void 0 : optsNode.content;
|
|
452
|
+
if (content instanceof Buffer || content instanceof Uint8Array) {
|
|
453
|
+
publicKey = content;
|
|
454
|
+
}
|
|
455
|
+
else if (typeof content === 'string') {
|
|
456
|
+
try {
|
|
457
|
+
publicKey = JSON.parse(content);
|
|
458
|
+
}
|
|
459
|
+
catch (_d) {
|
|
460
|
+
publicKey = Buffer.from(content, 'utf-8');
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
ev.emit('pair.passkey.request', { publicKey, raw: node });
|
|
464
|
+
logger.info('passkey_prologue_request — use WhatsApp Web + extensão');
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
case 'crsc_continuation': {
|
|
468
|
+
const primaryNode = (0, WABinary_1.getBinaryNodeChild)(node, 'primary_ephemeral_identity');
|
|
469
|
+
ev.emit('pair.passkey.confirmation', { raw: node });
|
|
470
|
+
logger.info({ hasPrimary: !!primaryNode }, 'passkey continuation (crsc_continuation)');
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
445
473
|
}
|
|
446
474
|
if (Object.keys(result).length) {
|
|
447
475
|
return result;
|
|
@@ -514,7 +542,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
514
542
|
fromMe,
|
|
515
543
|
participant: attrs.participant
|
|
516
544
|
};
|
|
517
|
-
if (shouldIgnoreJid(remoteJid) && remoteJid !== '@s.whatsapp.net') {
|
|
545
|
+
if (remoteJid && shouldIgnoreJid(remoteJid) && remoteJid !== '@s.whatsapp.net') {
|
|
518
546
|
logger.debug({ remoteJid }, 'ignoring receipt from jid');
|
|
519
547
|
await sendMessageAck(node);
|
|
520
548
|
return;
|
|
@@ -614,12 +642,21 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
614
642
|
}
|
|
615
643
|
};
|
|
616
644
|
const handleMessage = async (node) => {
|
|
617
|
-
var _a, _b, _c;
|
|
645
|
+
var _a, _b, _c, _d, _e;
|
|
618
646
|
if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
|
|
619
647
|
logger.debug({ key: node.attrs.key }, 'ignored message');
|
|
620
648
|
await sendMessageAck(node);
|
|
621
649
|
return;
|
|
622
650
|
}
|
|
651
|
+
const checkisValid = (0, WABinary_1.getBinaryNodeChild)(node, 'unavailable');
|
|
652
|
+
if (checkisValid && checkisValid.attrs.type === 'view_once') {
|
|
653
|
+
logger.debug({ key: node.attrs.key }, 'ignored msmsg viewOnce message');
|
|
654
|
+
const { fullMessage } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '');
|
|
655
|
+
fullMessage.viewOnce = true;
|
|
656
|
+
await upsertMessage(fullMessage, 'append');
|
|
657
|
+
await sendMessageAck(node);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
623
660
|
const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
|
|
624
661
|
// TODO: temporary fix for crashes and issues resulting of failed msmsg decryption
|
|
625
662
|
if (encNode && encNode.attrs.type === 'msmsg') {
|
|
@@ -655,6 +692,12 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
655
692
|
node.attrs.sender_pn) {
|
|
656
693
|
ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn });
|
|
657
694
|
}
|
|
695
|
+
if (msg.messageStubType === WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT) {
|
|
696
|
+
if (((_d = msg === null || msg === void 0 ? void 0 : msg.messageStubParameters) === null || _d === void 0 ? void 0 : _d[0]) === Utils_1.MISSING_KEYS_ERROR_TEXT ||
|
|
697
|
+
((_e = msg.messageStubParameters) === null || _e === void 0 ? void 0 : _e[0]) === Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT) {
|
|
698
|
+
return sendMessageAck(node);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
658
701
|
try {
|
|
659
702
|
await Promise.all([
|
|
660
703
|
processingMutex.mutex(async () => {
|
|
@@ -671,7 +714,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
671
714
|
return;
|
|
672
715
|
}
|
|
673
716
|
const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
|
|
674
|
-
await sendRetryRequest(node,
|
|
717
|
+
await sendRetryRequest(node, true);
|
|
675
718
|
if (retryRequestDelayMs) {
|
|
676
719
|
await (0, Utils_1.delay)(retryRequestDelayMs);
|
|
677
720
|
}
|
|
@@ -715,6 +758,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
715
758
|
]);
|
|
716
759
|
}
|
|
717
760
|
catch (error) {
|
|
761
|
+
sendMessageAck(node);
|
|
718
762
|
logger.error({ error, node }, 'error in handling message');
|
|
719
763
|
}
|
|
720
764
|
};
|
|
@@ -812,6 +856,40 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
812
856
|
ev.emit('call', [call]);
|
|
813
857
|
await sendMessageAck(node);
|
|
814
858
|
};
|
|
859
|
+
/** tracks message IDs that have already been retried for error 463 — prevents retry loops */
|
|
860
|
+
const tcTokenRetriedMsgIds = new Set();
|
|
861
|
+
/** tracks JIDs for which we have stored tctokens — used for periodic pruning */
|
|
862
|
+
const tcTokenKnownJids = new Set();
|
|
863
|
+
const retryMissingTcToken = async (key, msgId, jid) => {
|
|
864
|
+
if (!msgId || !jid || tcTokenRetriedMsgIds.has(msgId)) {
|
|
865
|
+
if (msgId && tcTokenRetriedMsgIds.has(msgId)) {
|
|
866
|
+
logger.warn({ msgId, from: jid }, 'error 463: already retried, giving up');
|
|
867
|
+
}
|
|
868
|
+
return false;
|
|
869
|
+
}
|
|
870
|
+
// Each entry auto-expires via setTimeout(60s), so the set
|
|
871
|
+
// is naturally bounded under normal conditions.
|
|
872
|
+
tcTokenRetriedMsgIds.add(msgId);
|
|
873
|
+
setTimeout(() => tcTokenRetriedMsgIds.delete(msgId), 60000);
|
|
874
|
+
const msg = await getMessage(key);
|
|
875
|
+
if (!msg) {
|
|
876
|
+
logger.warn({ msgId, from: jid }, 'error 463: no message found for retry');
|
|
877
|
+
return false;
|
|
878
|
+
}
|
|
879
|
+
try {
|
|
880
|
+
await (0, Utils_1.delay)(1500);
|
|
881
|
+
await relayMessage(jid, msg, {
|
|
882
|
+
messageId: msgId,
|
|
883
|
+
useUserDevicesCache: true
|
|
884
|
+
});
|
|
885
|
+
logger.info({ msgId, from: jid }, 'error 463 retry succeeded');
|
|
886
|
+
return true;
|
|
887
|
+
}
|
|
888
|
+
catch (retryErr) {
|
|
889
|
+
logger.warn({ msgId, err: retryErr === null || retryErr === void 0 ? void 0 : retryErr.message }, 'error 463 retry failed');
|
|
890
|
+
return false;
|
|
891
|
+
}
|
|
892
|
+
};
|
|
815
893
|
const handleBadAck = async ({ attrs }) => {
|
|
816
894
|
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
|
|
817
895
|
// WARNING: REFRAIN FROM ENABLING THIS FOR NOW. IT WILL CAUSE A LOOP
|
|
@@ -830,7 +908,41 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
830
908
|
// error in acknowledgement,
|
|
831
909
|
// device could not display the message
|
|
832
910
|
if (attrs.error) {
|
|
833
|
-
|
|
911
|
+
if (attrs.error === Utils_1.SERVER_ERROR_CODES.MissingTcToken) {
|
|
912
|
+
const reachoutTimeLock = await fetchAccountReachoutTimelock().catch(err => {
|
|
913
|
+
logger.warn({ err: err === null || err === void 0 ? void 0 : err.message }, 'failed to fetch reachout timelock after error 463');
|
|
914
|
+
return undefined;
|
|
915
|
+
});
|
|
916
|
+
await fetchNewChatMessageCap().catch(err => {
|
|
917
|
+
logger.debug({ err: err === null || err === void 0 ? void 0 : err.message }, 'failed to fetch new chat message cap after error 463');
|
|
918
|
+
});
|
|
919
|
+
if (reachoutTimeLock === null || reachoutTimeLock === void 0 ? void 0 : reachoutTimeLock.isActive) {
|
|
920
|
+
ev.emit('messages.update', [
|
|
921
|
+
{
|
|
922
|
+
key,
|
|
923
|
+
update: {
|
|
924
|
+
status: Types_1.WAMessageStatus.ERROR,
|
|
925
|
+
messageStubParameters: [attrs.error, Utils_1.ACCOUNT_RESTRICTED_TEXT]
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
]);
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
// Single retry: the original getPrivacyTokens IQ triggered token issuance.
|
|
932
|
+
// After a brief delay the server should have pushed a privacy_token
|
|
933
|
+
// notification, making the re-send succeed.
|
|
934
|
+
const msgId = attrs.id;
|
|
935
|
+
const jid = (0, WABinary_1.jidNormalizedUser)(attrs.from);
|
|
936
|
+
if (await retryMissingTcToken(key, msgId, jid)) {
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
else if (attrs.error === Utils_1.SERVER_ERROR_CODES.SmaxInvalid) {
|
|
941
|
+
logger.warn({ msgId: attrs.id, from: attrs.from }, 'smax-invalid (479): stanza rejected by server — likely stale device session or malformed addressing');
|
|
942
|
+
}
|
|
943
|
+
else {
|
|
944
|
+
logger.warn({ attrs }, 'received error in ack');
|
|
945
|
+
}
|
|
834
946
|
ev.emit('messages.update', [
|
|
835
947
|
{
|
|
836
948
|
key,
|
|
@@ -879,7 +991,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
879
991
|
}
|
|
880
992
|
isProcessing = false;
|
|
881
993
|
};
|
|
882
|
-
promise().catch(error =>
|
|
994
|
+
promise().catch(error => {
|
|
995
|
+
onUnexpectedError(error, 'processing offline nodes');
|
|
996
|
+
sendMessageAck(node);
|
|
997
|
+
});
|
|
883
998
|
};
|
|
884
999
|
return { enqueue };
|
|
885
1000
|
};
|
|
@@ -1027,6 +1142,61 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1027
1142
|
break;
|
|
1028
1143
|
}
|
|
1029
1144
|
}
|
|
1145
|
+
const handlePrivacyTokenNotification = async (node) => {
|
|
1146
|
+
const tokensNode = (0, WABinary_1.getBinaryNodeChild)(node, 'tokens');
|
|
1147
|
+
const from = (0, WABinary_1.jidNormalizedUser)(node.attrs.from);
|
|
1148
|
+
const issueTimestamp = (0, Utils_1.unixTimestampSeconds)();
|
|
1149
|
+
if (!tokensNode)
|
|
1150
|
+
return;
|
|
1151
|
+
const tokenNodes = (0, WABinary_1.getBinaryNodeChildren)(tokensNode, 'token');
|
|
1152
|
+
for (const tokenNode of tokenNodes) {
|
|
1153
|
+
const { attrs, content } = tokenNode;
|
|
1154
|
+
const type = attrs.type;
|
|
1155
|
+
const timestamp = attrs.t;
|
|
1156
|
+
if (type === 'trusted_contact' && content instanceof Buffer) {
|
|
1157
|
+
logger.debug({
|
|
1158
|
+
from,
|
|
1159
|
+
timestamp,
|
|
1160
|
+
tcToken: content
|
|
1161
|
+
}, 'received trusted contact token');
|
|
1162
|
+
await authState.keys.set({
|
|
1163
|
+
'contacts-tc-token': { [from]: { token: content, timestamp, senderTimestamp: issueTimestamp } }
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
const handlePresenceUpdate = ({ tag, attrs, content }) => {
|
|
1169
|
+
var _a;
|
|
1170
|
+
let presence;
|
|
1171
|
+
const jid = attrs.from;
|
|
1172
|
+
const participant = attrs.participant || attrs.from;
|
|
1173
|
+
if (shouldIgnoreJid(jid)) {
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
if (tag === 'presence') {
|
|
1177
|
+
presence = {
|
|
1178
|
+
lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
|
|
1179
|
+
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
else if (Array.isArray(content)) {
|
|
1183
|
+
const [firstChild] = content;
|
|
1184
|
+
let type = firstChild.tag;
|
|
1185
|
+
if (type === 'paused') {
|
|
1186
|
+
type = 'available';
|
|
1187
|
+
}
|
|
1188
|
+
if (((_a = firstChild.attrs) === null || _a === void 0 ? void 0 : _a.media) === 'audio') {
|
|
1189
|
+
type = 'recording';
|
|
1190
|
+
}
|
|
1191
|
+
presence = { lastKnownPresence: type };
|
|
1192
|
+
}
|
|
1193
|
+
else {
|
|
1194
|
+
logger.error({ tag, attrs, content }, 'recv invalid presence node');
|
|
1195
|
+
}
|
|
1196
|
+
if (presence) {
|
|
1197
|
+
ev.emit('presence.update', { id: jid, presences: { [participant]: presence } });
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1030
1200
|
// recv a message
|
|
1031
1201
|
ws.on('CB:message', (node) => {
|
|
1032
1202
|
processNode('message', node, 'processing message', handleMessage);
|
|
@@ -1043,6 +1213,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1043
1213
|
ws.on('CB:ack,class:message', (node) => {
|
|
1044
1214
|
handleBadAck(node).catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
1045
1215
|
});
|
|
1216
|
+
ws.on('CB:presence', handlePresenceUpdate);
|
|
1217
|
+
ws.on('CB:chatstate', handlePresenceUpdate);
|
|
1046
1218
|
ev.on('call', ([call]) => {
|
|
1047
1219
|
// missed call + group call notification message generation
|
|
1048
1220
|
if (call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
|
|
@@ -1083,6 +1255,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1083
1255
|
sendRetryRequest,
|
|
1084
1256
|
rejectCall,
|
|
1085
1257
|
fetchMessageHistory,
|
|
1258
|
+
fetchNewChatMessageCap,
|
|
1259
|
+
fetchAccountReachoutTimelock,
|
|
1086
1260
|
requestPlaceholderResend
|
|
1087
1261
|
};
|
|
1088
1262
|
};
|