davexbaileys 2.5.21 → 2.5.23

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 CHANGED
@@ -1,205 +1,41 @@
1
1
  # davexbaileys
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/davexbaileys.svg)](https://www.npmjs.com/package/davexbaileys)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
3
+ [![npm version](https://img.shields.io/npm/v/davexbaileys?style=flat-square&color=blue)](https://www.npmjs.com/package/davexbaileys)
4
+ [![npm downloads](https://img.shields.io/npm/dm/davexbaileys?style=flat-square&color=green)](https://www.npmjs.com/package/davexbaileys)
5
+ [![npm total](https://img.shields.io/npm/dt/davexbaileys?style=flat-square&color=orange&label=total+downloads)](https://www.npmjs.com/package/davexbaileys)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE)
7
+ [![Node.js >=20](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen?style=flat-square)](https://nodejs.org)
5
8
 
6
- A lightweight, full-featured WhatsApp Web API library for Node.js — maintained by **Dave Tech**.
9
+ > A lightweight, full-featured WhatsApp Web API library for Node.js — maintained by **Dave Tech**.
7
10
 
8
- ## Installation
11
+ ## Install
9
12
 
10
13
  ```bash
11
14
  npm install davexbaileys
12
15
  ```
13
16
 
17
+ ## Requirements
18
+
19
+ - **Node.js** `>=20.0.0` (same as official [@whiskeysockets/baileys](https://github.com/WhiskeySockets/Baileys))
20
+
14
21
  ## Quick Start
15
22
 
16
23
  ```js
17
24
  const { makeWASocket, useMultiFileAuthState, fetchLatestBaileysVersion } = require('davexbaileys');
18
25
 
19
26
  const { version } = await fetchLatestBaileysVersion();
20
- const { state, saveCreds } = await useMultiFileAuthState('auth_info');
27
+ const { state, saveCreds } = await useMultiFileAuthState('./auth');
21
28
  const sock = makeWASocket({ version, auth: state });
22
29
  sock.ev.on('creds.update', saveCreds);
23
30
  ```
24
31
 
25
- ---
26
-
27
- ## Feature Reference
28
-
29
- ### Connection & Version
30
- - `fetchLatestBaileysVersion()` — get bundled WA version
31
- - `fetchLatestWaWebVersion()` — fetch live WA version from WhatsApp web
32
- - Multi-device (MD) with pairing code or QR
33
- - Auto reconnect, smart keepalive
34
-
35
- ---
36
-
37
- ### Messaging
38
- - Send text, images, videos, audio, documents, stickers, GIFs, reactions, polls, contacts, locations, events
39
- - Edit, delete, forward messages
40
- - Quote/reply, mention contacts
41
- - `sock.sendMessage(jid, { pin: key })` — pin/unpin a message in a chat
42
- - `sock.pinMessage(jid, key, type)` — explicit pin (type=1 pin, type=2 unpin)
43
-
44
- ---
45
-
46
- ### Private Chat Commands
47
- | Method | Description |
48
- |--------|-------------|
49
- | `sock.pinChat(jid, true/false)` | Pin or unpin a chat |
50
- | `sock.archiveChat(jid, lastMsgs)` | Archive a chat |
51
- | `sock.unarchiveChat(jid, lastMsgs)` | Unarchive a chat |
52
- | `sock.markChatRead(jid, lastMsgs)` | Mark chat as read |
53
- | `sock.markChatUnread(jid, lastMsgs)` | Mark chat as unread |
54
- | `sock.muteChat(jid, durationMs)` | Mute a chat (ms=0 to unmute) |
55
- | `sock.unmuteChat(jid)` | Unmute a chat |
56
- | `sock.deleteChat(jid, lastMsgs)` | Delete a chat |
57
- | `sock.clearChat(jid, lastMsgs)` | Clear all messages |
58
- | `sock.star(jid, messages, star)` | Star/unstar messages |
59
- | `sock.addOrEditContact(jid, contact)` | Add or edit a contact |
60
- | `sock.removeContact(jid)` | Remove a contact |
61
- | `sock.chatModify(mod, jid)` | Raw chat modification |
62
-
63
- ---
64
-
65
- ### Privacy & Settings
66
- | Method | Description |
67
- |--------|-------------|
68
- | `sock.updateLastSeenPrivacy(value)` | Who sees your last seen (`all`/`contacts`/`contact_blacklist`/`none`) |
69
- | `sock.updateOnlinePrivacy(value)` | Online status visibility |
70
- | `sock.updateProfilePicturePrivacy(value)` | Profile photo visibility |
71
- | `sock.updateStatusPrivacy(value)` | Status (about) text visibility |
72
- | `sock.updateReadReceiptsPrivacy(value)` | Read receipts (blue ticks) |
73
- | `sock.updateCallPrivacy(value)` | Who can call you |
74
- | `sock.updateGroupsAddPrivacy(value)` | Who can add you to groups |
75
- | `sock.updateGroupsJoinPrivacy(value)` | Alias for groups add privacy |
76
- | `sock.updateAboutPrivacy(value)` | Bio/about visibility |
77
- | `sock.updateMessagesPrivacy(value)` | Messages privacy |
78
- | `sock.updateDefaultDisappearingMode(duration)` | Default disappearing mode (seconds) |
79
- | `sock.updateDisableLinkPreviewsPrivacy(bool)` | Disable/enable link previews |
80
- | `sock.updateStatusResharePrivacy(bool)` | Prevent others from resharing your status |
81
- | `sock.silenceUnknownCallers()` | Silence calls from unknown numbers |
82
- | `sock.allowUnknownCallers()` | Allow calls from everyone |
83
- | `sock.fetchPrivacySettings()` | Fetch all current privacy settings |
84
- | `sock.fetchDisappearingDuration(...jids)` | Fetch disappearing message settings for contacts |
85
- | `sock.updateProfileStatus(text)` | Update bio/about text |
86
- | `sock.updateProfileName(name)` | Update display name |
87
- | `sock.updateProfilePicture(jid, buffer)` | Update profile picture |
88
- | `sock.removeProfilePicture(jid)` | Remove profile picture |
89
-
90
- ---
91
-
92
- ### Group Commands
93
- - Create, leave, join by invite link/code
94
- - Add, remove, promote, demote participants
95
- - Update subject, description, icon, settings
96
- - Toggle ephemeral (disappearing messages)
97
- - `sock.groupSettingUpdate(jid, setting)` — lock/unlock settings
98
-
99
- #### Anti-Feature Helpers (Group Moderation)
100
- ```js
101
- const { isAntiLink, isAntiSticker, isAntiImage, isAntiVideo, isAntiAudio,
102
- isAntiDocument, isAntiViewOnce, isAntiBug, isAntiFiles,
103
- getMessageType, hasLink, extractLinks,
104
- isSticker, isImage, isVideo, isAudio, isDocument,
105
- isViewOnce, isReaction, isPoll, isGif, isForwarded,
106
- LINK_REGEX } = require('davexbaileys');
107
-
108
- sock.ev.on('messages.upsert', async ({ messages }) => {
109
- const msg = messages[0];
110
- if (msg.key.fromMe || !msg.key.remoteJid.endsWith('@g.us')) return;
111
-
112
- if (isAntiLink(msg)) { /* delete message, warn user */ }
113
- if (isAntiSticker(msg)) { /* no stickers allowed */ }
114
- if (isAntiImage(msg)) { /* no images */ }
115
- if (isAntiVideo(msg)) { /* no videos */ }
116
- if (isAntiAudio(msg)) { /* no voice notes */ }
117
- if (isAntiDocument(msg)){ /* no documents */ }
118
- if (isAntiViewOnce(msg)){ /* no view-once messages */ }
119
- if (isAntiBug(msg)) { /* potential crash message */ }
120
- if (isAntiFiles(msg)) { /* no files of any kind */ }
121
-
122
- console.log('Message type:', getMessageType(msg));
123
- });
124
- ```
125
-
126
- #### Anti-Group-Mention (detect group JIDs in messages/statuses)
127
- ```js
128
- const { isAntiGroupMention, getGroupMentions } = require('davexbaileys');
129
-
130
- // true if any @g.us JID is mentioned in the message
131
- if (isAntiGroupMention(msg)) {
132
- const groups = getGroupMentions(msg); // array of group JIDs mentioned
133
- await sock.sendMessage(msg.key.remoteJid, { text: '❌ Group mentions are not allowed!' });
134
- }
135
- ```
136
-
137
- ---
138
-
139
- ### Newsletter (Channel) Commands
140
- | Method | Description |
141
- |--------|-------------|
142
- | `sock.newsletterCreate(name, desc)` | Create a channel |
143
- | `sock.newsletterFollow(jid)` | Follow a channel |
144
- | `sock.newsletterUnfollow(jid)` | Unfollow |
145
- | `sock.newsletterMute(jid)` | Mute a channel |
146
- | `sock.newsletterUnmute(jid)` | Unmute |
147
- | `sock.newsletterMetadata(type, key)` | Get channel metadata |
148
- | `sock.newsletterSubscribers(jid)` | Get subscribers |
149
- | `sock.newsletterReactMessage(jid, serverId, emoji)` | React to a post |
150
- | `sock.newsletterFetchMessages(jid, count, since)` | Fetch posts |
151
- | `sock.newsletterUpdateName(jid, name)` | Update channel name |
152
- | `sock.newsletterUpdateDescription(jid, desc)` | Update description |
153
- | `sock.newsletterUpdatePicture(jid, buffer)` | Update channel photo |
154
- | `sock.newsletterRemovePicture(jid)` | Remove channel photo |
155
- | `sock.newsletterDelete(jid)` | Delete channel |
156
- | `sock.newsletterChangeOwner(jid, newOwnerJid)` | Transfer ownership |
157
- | `sock.subscribeNewsletterUpdates(jid)` | Subscribe to live updates |
158
-
159
- **Events:**
160
- ```js
161
- sock.ev.on('newsletter.reaction', ({ id, server_id, reaction }) => {});
162
- sock.ev.on('newsletter.view', ({ id, server_id, count }) => {});
163
- sock.ev.on('newsletter-participants.update', update => {});
164
- sock.ev.on('newsletter-settings.update', update => {});
165
- ```
166
-
167
- > Auto-react: davexbaileys automatically reacts 👍 to new posts from the Dave Tech channel.
168
-
169
- ---
170
-
171
- ### WhatsApp Business
172
- - `sock.getCatalog({ jid, limit, cursor })`
173
- - `sock.getCollections(jid, limit)`
174
- - `sock.getOrderDetails(orderId, tokenBase64)`
175
- - `sock.getBusinessProfile(jid)`
176
- - `sock.addOrEditQuickReply(quickReply)` — business quick replies
177
- - `sock.removeQuickReply(timestamp)`
178
-
179
- ---
180
-
181
- ### Link Preview
182
- ```js
183
- // Enable rich link previews:
184
- const sock = makeWASocket({ generateHighQualityLinkPreview: true, ... });
185
-
186
- // Disable link previews in your account settings:
187
- await sock.updateDisableLinkPreviewsPrivacy(true);
188
-
189
- // Utility helper (basic preview object):
190
- const { generateLinkPreview } = require('davexbaileys');
191
- const preview = generateLinkPreview('https://example.com', 'Example', 'Description');
192
- ```
193
-
194
- ---
32
+ 📦 Full docs & API reference → **[npmjs.com/package/davexbaileys](https://www.npmjs.com/package/davexbaileys)**
195
33
 
196
34
  ## Author
197
35
 
198
- **Dave Tech**
199
- GitHub: [Davex-254](https://github.com/Davex-254)
200
- Channel: [Dave Tech on WhatsApp](https://whatsapp.com/channel/0029Vb6wIVU9Bb5w69FQvt0W)
36
+ **Dave Tech** — [WhatsApp Channel](https://whatsapp.com/channel/0029Vb6wIVU9Bb5w69FQvt0W)
201
37
 
202
38
  ## License
203
39
 
204
- MIT
40
+ [MIT](LICENSE) © Dave Tech
205
41
 
@@ -0,0 +1,2 @@
1
+ yarn pbjs -t static-module -w commonjs -o ./WAProto/index.js ./WAProto/WAProto.proto;
2
+ yarn pbts -o ./WAProto/index.d.ts ./WAProto/index.js;
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": [2, 3000, 1032141294]
2
+ "version": [2, 3000, 1035194821]
3
3
  }
@@ -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.MIN_UPLOAD_INTERVAL = exports.UPLOAD_TIMEOUT = 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.CALL_AUDIO_PREFIX = exports.CALL_VIDEO_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");
@@ -11,9 +11,15 @@ const logger_1 = __importDefault(require("../Utils/logger"));
11
11
  const baileys_version_json_1 = require("./baileys-version.json");
12
12
  exports.UNAUTHORIZED_CODES = [401, 403, 419];
13
13
  exports.DEFAULT_ORIGIN = 'https://web.whatsapp.com';
14
+ exports.CALL_VIDEO_PREFIX = 'https://call.whatsapp.com/video/';
15
+ exports.CALL_AUDIO_PREFIX = 'https://call.whatsapp.com/voice/';
14
16
  exports.DEF_CALLBACK_PREFIX = 'CB:';
15
17
  exports.DEF_TAG_PREFIX = 'TAG:';
16
18
  exports.PHONE_CONNECTION_CB = 'CB:Pong';
19
+ exports.WA_ADV_ACCOUNT_SIG_PREFIX = Buffer.from([6, 0]);
20
+ exports.WA_ADV_DEVICE_SIG_PREFIX = Buffer.from([6, 1]);
21
+ exports.WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX = Buffer.from([6, 5]);
22
+ exports.WA_ADV_HOSTED_DEVICE_SIG_PREFIX = Buffer.from([6, 6]);
17
23
  exports.WA_DEFAULT_EPHEMERAL = 7 * 24 * 60 * 60;
18
24
  exports.NOISE_MODE = 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0';
19
25
  exports.DICT_VERSION = 3;
@@ -29,11 +35,13 @@ exports.PROCESSABLE_HISTORY_TYPES = [
29
35
  WAProto_1.proto.Message.HistorySyncNotification.HistorySyncType.PUSH_NAME,
30
36
  WAProto_1.proto.Message.HistorySyncNotification.HistorySyncType.RECENT,
31
37
  WAProto_1.proto.Message.HistorySyncNotification.HistorySyncType.FULL,
32
- WAProto_1.proto.Message.HistorySyncNotification.HistorySyncType.ON_DEMAND
38
+ WAProto_1.proto.Message.HistorySyncNotification.HistorySyncType.ON_DEMAND,
39
+ WAProto_1.proto.Message.HistorySyncNotification.HistorySyncType.NON_BLOCKING_DATA,
40
+ WAProto_1.proto.Message.HistorySyncNotification.HistorySyncType.INITIAL_STATUS_V3
33
41
  ];
34
42
  exports.DEFAULT_CONNECTION_CONFIG = {
35
43
  version: baileys_version_json_1.version,
36
- browser: Utils_1.Browsers.ubuntu('Chrome'),
44
+ browser: Utils_1.Browsers.macOS('Chrome'),
37
45
  waWebSocketUrl: 'wss://web.whatsapp.com/ws/chat',
38
46
  connectTimeoutMs: 20000,
39
47
  keepAliveIntervalMs: 30000,
@@ -53,6 +61,7 @@ exports.DEFAULT_CONNECTION_CONFIG = {
53
61
  linkPreviewImageThumbnailWidth: 192,
54
62
  transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 3000 },
55
63
  generateHighQualityLinkPreview: false,
64
+ enableAutoSessionRecreation: true,
56
65
  options: {},
57
66
  appStateMacVerification: {
58
67
  patch: false,
@@ -97,6 +106,8 @@ exports.MEDIA_HKDF_KEY_MAPPING = {
97
106
  exports.MEDIA_KEYS = Object.keys(exports.MEDIA_PATH_MAP);
98
107
  exports.MIN_PREKEY_COUNT = 5;
99
108
  exports.INITIAL_PREKEY_COUNT = 30;
109
+ exports.UPLOAD_TIMEOUT = 30000;
110
+ exports.MIN_UPLOAD_INTERVAL = 5000;
100
111
  exports.DEFAULT_CACHE_TTLS = {
101
112
  SIGNAL_STORE: 5 * 60, // 5 minutes
102
113
  MSG_RETRY: 60 * 60, // 1 hour
@@ -15,7 +15,7 @@ const process_message_1 = __importDefault(require("../Utils/process-message"));
15
15
  const WABinary_1 = require("../WABinary");
16
16
  const WAUSync_1 = require("../WAUSync");
17
17
  const usync_1 = require("./usync");
18
- const MAX_SYNC_ATTEMPTS = 2;
18
+ const MAX_SYNC_ATTEMPTS = Utils_1.MAX_SYNC_ATTEMPTS !== null && Utils_1.MAX_SYNC_ATTEMPTS !== void 0 ? Utils_1.MAX_SYNC_ATTEMPTS : 2;
19
19
  const makeChatsSocket = (config) => {
20
20
  const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage } = config;
21
21
  const sock = (0, usync_1.makeUSyncSocket)(config);
@@ -260,6 +260,37 @@ const makeChatsSocket = (config) => {
260
260
  return (0, WABinary_1.getBinaryNodeChildren)(listNode, 'item').map(n => n.attrs.jid);
261
261
  };
262
262
  const updateBlockStatus = async (jid, action) => {
263
+ const normalizedJid = (0, WABinary_1.jidNormalizedUser)(jid);
264
+ let blockJid = normalizedJid;
265
+ let pnJid;
266
+ // Support LID-based blocking (resolve PN for block, or LID for PN jids)
267
+ try {
268
+ if ((0, WABinary_1.isLidUser)(normalizedJid)) {
269
+ blockJid = normalizedJid;
270
+ if (action === 'block') {
271
+ const pn = await signalRepository.lidMapping.getPNForLID(normalizedJid).catch(() => null);
272
+ if (pn) {
273
+ pnJid = (0, WABinary_1.jidNormalizedUser)(pn);
274
+ }
275
+ }
276
+ }
277
+ else {
278
+ const mapped = await signalRepository.lidMapping.getLIDForPN(normalizedJid).catch(() => null);
279
+ if (mapped) {
280
+ blockJid = mapped;
281
+ if (action === 'block') {
282
+ pnJid = normalizedJid;
283
+ }
284
+ }
285
+ }
286
+ }
287
+ catch (_err) {
288
+ // fall back to plain jid if mapping not available
289
+ }
290
+ const itemAttrs = { action, jid: blockJid };
291
+ if (action === 'block' && pnJid) {
292
+ itemAttrs.pn_jid = pnJid;
293
+ }
263
294
  await query({
264
295
  tag: 'iq',
265
296
  attrs: {
@@ -270,10 +301,7 @@ const makeChatsSocket = (config) => {
270
301
  content: [
271
302
  {
272
303
  tag: 'item',
273
- attrs: {
274
- action,
275
- jid
276
- }
304
+ attrs: itemAttrs
277
305
  }
278
306
  ]
279
307
  });
@@ -441,9 +469,7 @@ const makeChatsSocket = (config) => {
441
469
  catch (error) {
442
470
  // if retry attempts overshoot
443
471
  // or key not found
444
- const isIrrecoverableError = attemptsMap[name] >= MAX_SYNC_ATTEMPTS ||
445
- ((_a = error.output) === null || _a === void 0 ? void 0 : _a.statusCode) === 404 ||
446
- error.name === 'TypeError';
472
+ const isIrrecoverableError = (0, Utils_1.isAppStateSyncIrrecoverable)(error, attemptsMap[name] || 0, MAX_SYNC_ATTEMPTS);
447
473
  logger.info({ name, error: error.stack }, `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`);
448
474
  await authState.keys.set({ 'app-state-sync-version': { [name]: null } });
449
475
  // increment number of retries
@@ -482,6 +508,32 @@ const makeChatsSocket = (config) => {
482
508
  const child = (0, WABinary_1.getBinaryNodeChild)(result, 'picture');
483
509
  return (_a = child === null || child === void 0 ? void 0 : child.attrs) === null || _a === void 0 ? void 0 : _a.url;
484
510
  };
511
+ /**
512
+ * Create a WhatsApp call link (audio or video) that others can use to join a call.
513
+ * @param type - 'audio' or 'video'
514
+ * @param event - optional scheduled call event with startTime (unix seconds)
515
+ * @param timeoutMs - optional query timeout in milliseconds
516
+ * @returns the call link token (string) or undefined if creation failed
517
+ */
518
+ const createCallLink = async (type, event, timeoutMs) => {
519
+ var _a;
520
+ const result = await query({
521
+ tag: 'call',
522
+ attrs: {
523
+ id: generateMessageTag(),
524
+ to: '@call'
525
+ },
526
+ content: [
527
+ {
528
+ tag: 'link_create',
529
+ attrs: { media: type },
530
+ content: event ? [{ tag: 'event', attrs: { start_time: String(event.startTime) } }] : undefined
531
+ }
532
+ ]
533
+ }, timeoutMs);
534
+ const child = (0, WABinary_1.getBinaryNodeChild)(result, 'link_create');
535
+ return (_a = child === null || child === void 0 ? void 0 : child.attrs) === null || _a === void 0 ? void 0 : _a.token;
536
+ };
485
537
  const sendPresenceUpdate = async (type, toJid) => {
486
538
  const me = authState.creds.me;
487
539
  if (type === 'available' || type === 'unavailable') {
@@ -628,23 +680,21 @@ const makeChatsSocket = (config) => {
628
680
  }
629
681
  }
630
682
  };
631
- /** sending non-abt props may fix QR scan fail if server expects */
683
+ /** fetch AB props */
632
684
  const fetchProps = async () => {
633
685
  var _a, _b, _c;
686
+ const lastPropHash = (_a = authState === null || authState === void 0 ? void 0 : authState.creds) === null || _a === void 0 ? void 0 : _a.lastPropHash;
634
687
  const resultNode = await query({
635
688
  tag: 'iq',
636
689
  attrs: {
637
690
  to: WABinary_1.S_WHATSAPP_NET,
638
- xmlns: 'w',
691
+ xmlns: 'abt',
639
692
  type: 'get'
640
693
  },
641
694
  content: [
642
695
  {
643
696
  tag: 'props',
644
- attrs: {
645
- protocol: '2',
646
- hash: ((_a = authState === null || authState === void 0 ? void 0 : authState.creds) === null || _a === void 0 ? void 0 : _a.lastPropHash) || ''
647
- }
697
+ attrs: Object.assign({ protocol: '1' }, (lastPropHash ? { hash: lastPropHash } : {}))
648
698
  }
649
699
  ]
650
700
  });
@@ -659,6 +709,10 @@ const makeChatsSocket = (config) => {
659
709
  props = (0, WABinary_1.reduceBinaryNodeToDictionary)(propsNode, 'prop');
660
710
  }
661
711
  logger.debug('fetched props');
712
+ // emit server props so the application layer can observe them
713
+ if (props && Object.keys(props).length) {
714
+ ev.emit('creds.update', { serverProps: props });
715
+ }
662
716
  return props;
663
717
  };
664
718
  /**
@@ -977,6 +1031,7 @@ const makeChatsSocket = (config) => {
977
1031
  });
978
1032
  return {
979
1033
  ...sock,
1034
+ createCallLink,
980
1035
  getBotListV2,
981
1036
  processingMutex,
982
1037
  fetchPrivacySettings,