@neelegirly/baileys 2.2.20 → 2.2.21

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
@@ -5,9 +5,9 @@
5
5
  ### *Die WhatsApp Web API mit sauberem Neelegirly-Glow-up*
6
6
  ### *QR Branding · Wrapper-Aware Update Notify · LID · Smart Queue*
7
7
 
8
- [![Version](https://img.shields.io/badge/Version-2.2.20-ff69b4?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@neelegirly/baileys)
9
- [![wa-api](https://img.shields.io/badge/wa--api-1.8.5-c77dff?style=for-the-badge)](https://www.npmjs.com/package/@neelegirly/wa-api)
10
- [![libsignal](https://img.shields.io/badge/libsignal-1.0.29-f4a261?style=for-the-badge)](https://www.npmjs.com/package/@neelegirly/libsignal)
8
+ [![Version](https://img.shields.io/badge/Version-2.2.21-ff69b4?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@neelegirly/baileys)
9
+ [![wa-api](https://img.shields.io/badge/wa--api-1.8.6-c77dff?style=for-the-badge)](https://www.npmjs.com/package/@neelegirly/wa-api)
10
+ [![libsignal](https://img.shields.io/badge/libsignal-1.0.30-f4a261?style=for-the-badge)](https://www.npmjs.com/package/@neelegirly/libsignal)
11
11
  [![Node](https://img.shields.io/badge/Node-16+-4caf50?style=for-the-badge&logo=node.js)](https://nodejs.org)
12
12
  [![npm](https://img.shields.io/npm/v/%40neelegirly%2Fbaileys?style=for-the-badge&color=ff69b4&logo=npm)](https://www.npmjs.com/package/@neelegirly/baileys)
13
13
 
@@ -15,9 +15,9 @@
15
15
  <img src="https://files.catbox.moe/5bqumy.jpeg" width="780" alt="@neelegirly/baileys Hero" />
16
16
  </p>
17
17
 
18
- <p align="center"><sub>2026 Glow-Up Edition · frische WA-API-, USync- und libsignal-Patches · Companion-Stack auf <strong>2.2.20 / 1.8.5 / 1.0.29</strong></sub></p>
18
+ <p align="center"><sub>2026 Glow-Up Edition · frische WA-API-, USync- und libsignal-Patches · Companion-Stack auf <strong>2.2.21 / 1.8.6 / 1.0.30</strong></sub></p>
19
19
 
20
- [**Installation**](#-installation) · [**Quickstart**](#-quickstart) · [**Highlights**](#-highlights) · [**QR Branding**](#-qr-branding--update-status) · [**Migration**](#-namespace-migration) · [**Release Notes**](#-release-notes-2220)
20
+ [**Installation**](#-installation) · [**Quickstart**](#-quickstart) · [**Highlights**](#-highlights) · [**QR Branding**](#-qr-branding--update-status) · [**Migration**](#-namespace-migration) · [**Release Notes**](#-release-notes-2221)
21
21
 
22
22
  </div>
23
23
 
@@ -42,14 +42,16 @@ Neelegirlys Variante von Baileys ist die WhatsApp-Web-Basis für stabile Bots, s
42
42
 
43
43
  ---
44
44
 
45
- ## 🆕 Was sich in `v2.2.20` geändert hat
45
+ ## 🆕 Was sich in `v2.2.21` geändert hat
46
46
 
47
47
  - ✅ Aktuelle Baileys-Upstream-Fixes vom 24./25. April 2026 sauber übernommen
48
48
  - ✅ AB-Props-Query nutzt wieder den aktuellen `abt`/Protocol-1-Flow
49
49
  - ✅ Username-Felder in Contacts, Gruppenmetadaten, Message Keys und USync ergänzt
50
50
  - ✅ App-State-Sync robuster bei fehlenden Keys, Snapshot-Retry und Reconnects
51
51
  - ✅ Call-Events, Album-Messages und History/Media-Streaming erweitert
52
- - ✅ libsignal-Dependency auf `1.0.29` mit TypeScript-Definitionen und ProtocolAddress-Typen aktualisiert
52
+ - ✅ Baileys-WA-API mit robusteren Group-/Message-Guards, Reachout-/Message-Cap-Abfragen und Newsletter-Join/Leave-IDs aktualisiert
53
+ - ✅ libsignal-Dependency auf `1.0.30` mit TypeScript-Definitionen und ProtocolAddress-Typen aktualisiert
54
+ - ✅ MEX-LID-Mappings werden in die Signal-Store-Anbindung übernommen
53
55
 
54
56
  ---
55
57
 
@@ -57,9 +59,9 @@ Neelegirlys Variante von Baileys ist die WhatsApp-Web-Basis für stabile Bots, s
57
59
 
58
60
  | Paket | Empfohlene Version |
59
61
  | --- | --- |
60
- | `@neelegirly/baileys` | `2.2.20` |
61
- | `@neelegirly/wa-api` | `1.8.5` |
62
- | `@neelegirly/libsignal` | `1.0.29` |
62
+ | `@neelegirly/baileys` | `2.2.21` |
63
+ | `@neelegirly/wa-api` | `1.8.6` |
64
+ | `@neelegirly/libsignal` | `1.0.30` |
63
65
 
64
66
  ---
65
67
 
@@ -68,22 +70,22 @@ Neelegirlys Variante von Baileys ist die WhatsApp-Web-Basis für stabile Bots, s
68
70
  ### npm
69
71
 
70
72
  ```bash
71
- npm install @neelegirly/baileys@2.2.20 @neelegirly/libsignal@1.0.29 --save-exact
73
+ npm install @neelegirly/baileys@2.2.21 @neelegirly/libsignal@1.0.30 --save-exact
72
74
  ```
73
75
 
74
76
  ### yarn
75
77
 
76
78
  ```bash
77
- yarn add @neelegirly/baileys@2.2.20 @neelegirly/libsignal@1.0.29 --exact
79
+ yarn add @neelegirly/baileys@2.2.21 @neelegirly/libsignal@1.0.30 --exact
78
80
  ```
79
81
 
80
82
  ### pnpm
81
83
 
82
84
  ```bash
83
- pnpm add @neelegirly/baileys@2.2.20 @neelegirly/libsignal@1.0.29 --save-exact
85
+ pnpm add @neelegirly/baileys@2.2.21 @neelegirly/libsignal@1.0.30 --save-exact
84
86
  ```
85
87
 
86
- > Für den kompletten Neelegirly-Stack passt dazu `@neelegirly/wa-api@1.8.5`.
88
+ > Für den kompletten Neelegirly-Stack passt dazu `@neelegirly/wa-api@1.8.6`.
87
89
 
88
90
  ---
89
91
 
@@ -136,9 +138,9 @@ start().catch(console.error)
136
138
 
137
139
  | Paket | Rolle |
138
140
  |------|-------|
139
- | `@neelegirly/baileys 2.2.20` | Socket, Events, Messaging |
140
- | `@neelegirly/libsignal 1.0.29` | Signal-Protokoll-Komponente |
141
- | `@neelegirly/wa-api 1.8.5` | Lifecycle-, Session- und Update-Wrapper |
141
+ | `@neelegirly/baileys 2.2.21` | Socket, Events, Messaging |
142
+ | `@neelegirly/libsignal 1.0.30` | Signal-Protokoll-Komponente |
143
+ | `@neelegirly/wa-api 1.8.6` | Lifecycle-, Session- und Update-Wrapper |
142
144
 
143
145
  ---
144
146
 
@@ -148,8 +150,8 @@ Beim QR-Scan werden automatisch Markenzeilen oberhalb und unterhalb des QR-Codes
148
150
 
149
151
  Typische Anzeige:
150
152
 
151
- - `Baileys Update-Status: up to date (2.2.20)`
152
- - `Wrapper Update-Status: up to date (1.8.5)`
153
+ - `Baileys Update-Status: up to date (2.2.21)`
154
+ - `Wrapper Update-Status: up to date (1.8.6)`
153
155
  - Bei echten Updates werden kompakte Hinweise auf `latest` eingeblendet
154
156
 
155
157
  Wenn kein Wrapper-Kontext vorhanden ist, bleibt die Anzeige sauber bei Baileys. Kein unnötiges Drama, nur QR. ✨
@@ -169,7 +171,7 @@ Wenn du direkt prüfen willst:
169
171
  ```ts
170
172
  import { checkNpmVersion } from '@neelegirly/baileys'
171
173
 
172
- const info = await checkNpmVersion('@neelegirly/baileys', '2.2.20', {
174
+ const info = await checkNpmVersion('@neelegirly/baileys', '2.2.21', {
173
175
  githubRepo: 'neelegirly/baileys'
174
176
  })
175
177
 
@@ -189,11 +191,14 @@ Wenn du vom Upstream kommst, nutze den Neelegirly-Scope:
189
191
 
190
192
  ---
191
193
 
192
- ## 📝 Release Notes `2.2.20`
194
+ ## 📝 Release Notes `2.2.21`
193
195
 
194
196
  - 🔧 Upstream-Änderungen vom 24./25. April 2026 portiert, ohne QR-/Update-Notify- oder Message-ID-Handling umzubauen
195
197
  - 🧩 Username-USync und Inbound-Username-Felder für Kontakte, Gruppen und Message Keys ergänzt
196
198
  - 🛡️ App-State-Sync und libsignal-LID/PN-Typen robuster gemacht
197
199
  - 🖼️ Album-Message-Sending und erweiterte Call-Event-Typen ergänzt
198
- - 🔐 libsignal auf `1.0.29` mit WhiskeySockets-TypeScript-Definitionen und ProtocolAddress-Typen gepinnt
199
- - 🔗 Companion-Stack auf `2.2.20 / 1.8.5 / 1.0.29` aktualisiert
200
+ - 🔐 libsignal auf `1.0.30` mit WhiskeySockets-TypeScript-Definitionen und ProtocolAddress-Typen gepinnt
201
+ - 🔗 Companion-Stack auf `2.2.21 / 1.8.6 / 1.0.30` aktualisiert
202
+ - 🛡️ Null-/Undefined-Pfade in Gruppen-, Nachrichten- und Chat-ID-Verarbeitung gehärtet
203
+ - 🧷 MEX-LID-Mappings werden in den Signal-Store übernommen
204
+ - 🧩 Reachout- und Message-Cap-WA-API-Abfragen plus TypeScript-Definitionen ergänzt
@@ -189,4 +189,6 @@ export declare const makeBusinessSocket: (config: SocketConfig) => {
189
189
  requestPairingCode: (phoneNumber: string, code?: string) => Promise<string>
190
190
  waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>
191
191
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<BinaryNode>
192
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>
193
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>
192
194
  }
@@ -100,4 +100,6 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
100
100
  * requires the last messages till the last message received required for archive & unread
101
101
  */
102
102
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<BinaryNode>
103
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>
104
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>
103
105
  }
@@ -224,5 +224,7 @@ export declare const makeCommunitiesSocket: (config: SocketConfig) => {
224
224
  requestPairingCode: (phoneNumber: string, customPairingCode?: string) => Promise<string>;
225
225
  waitForConnectionUpdate: (check: (u: Partial<import("../index.js").ConnectionState>) => Promise<boolean | undefined>, timeoutMs?: number) => Promise<void>;
226
226
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<any>;
227
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>;
228
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>;
227
229
  };
228
230
  export declare const extractCommunityMetadata: (result: BinaryNode) => GroupMetadata;
@@ -131,6 +131,8 @@ export declare const makeGroupsSocket: (config: SocketConfig) => {
131
131
  requestPairingCode: (phoneNumber: string, code?: string) => Promise<string>
132
132
  waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>
133
133
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<BinaryNode>
134
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>
135
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>
134
136
  }
135
137
 
136
138
  export declare const extractGroupMetadata: (result: BinaryNode) => GroupMetadata
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true })
3
3
 
4
4
  const WAProto_1 = require("../../WAProto")
5
+ const boom_1 = require("@hapi/boom")
5
6
  const Types_1 = require("../Types")
6
7
  const Utils_1 = require("../Utils")
7
8
  const WABinary_1 = require("../WABinary")
@@ -298,6 +299,21 @@ const makeGroupsSocket = (config) => {
298
299
 
299
300
  const extractGroupMetadata = (result) => {
300
301
  const group = WABinary_1.getBinaryNodeChild(result, 'group')
302
+ if (!group) {
303
+ const errorNode = WABinary_1.getBinaryNodeChild(result, 'error')
304
+ if (errorNode) {
305
+ const code = errorNode.attrs.code ? +errorNode.attrs.code : 500
306
+ const text = errorNode.attrs.text || 'group metadata query failed'
307
+ throw new boom_1.Boom(text, { statusCode: code, data: errorNode })
308
+ }
309
+
310
+ throw new boom_1.Boom('Invalid group metadata response: missing <group> node', { data: result })
311
+ }
312
+
313
+ if (!group.attrs.id) {
314
+ throw new boom_1.Boom('Invalid group metadata response: missing group id', { data: group })
315
+ }
316
+
301
317
  const descChild = WABinary_1.getBinaryNodeChild(group, 'description')
302
318
 
303
319
  let desc
@@ -191,6 +191,8 @@ declare const makeWASocket: (config: UserFacingSocketConfig) => {
191
191
  requestPairingCode: (phoneNumber: string, code?: string) => Promise<string>
192
192
  waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>
193
193
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<import("..").BinaryNode>
194
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>
195
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>
194
196
  }
195
197
 
196
198
  export default makeWASocket
@@ -179,4 +179,6 @@ export declare const makeMessagesRecvSocket: (config: SocketConfig) => {
179
179
  requestPairingCode: (phoneNumber: string, code?: string) => Promise<string>
180
180
  waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>
181
181
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<BinaryNode>
182
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>
183
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>
182
184
  }
@@ -48,6 +48,7 @@ const makeMessagesRecvSocket = (config) => {
48
48
  getUSyncDevices,
49
49
  createParticipantNodes,
50
50
  sendPeerDataOperationMessage,
51
+ fetchAccountReachoutTimelock,
51
52
  } = Neele;
52
53
 
53
54
  /** this mutex ensures that each retryRequest will wait for the previous one to finish */
@@ -677,9 +678,60 @@ const makeMessagesRecvSocket = (config) => {
677
678
  }
678
679
  };
679
680
 
680
- const handleMexNotification = (id, node) => {
681
- const operation = node?.attrs?.op_name;
682
- const content = JSON.parse(node?.content);
681
+ const handleMexNotification = async (id, node) => {
682
+ const updateNode = !node || node.content ? null : WABinary_1.getBinaryNodeChild(node, "update") || WABinary_1.getAllBinaryNodeChildren(node)[0];
683
+ const payloadNode = node?.content ? node : updateNode;
684
+ if (!payloadNode?.content) {
685
+ logger.warn({ node }, "Invalid mex newsletter notification");
686
+ return;
687
+ }
688
+
689
+ let content;
690
+ try {
691
+ const payloadContent = payloadNode.content;
692
+ if (Array.isArray(payloadContent)) {
693
+ logger.warn({ payloadNode }, "Invalid mex newsletter notification payload format");
694
+ return;
695
+ }
696
+
697
+ const contentBuf = typeof payloadContent === "string"
698
+ ? Buffer.from(payloadContent, "binary")
699
+ : Buffer.from(payloadContent);
700
+ content = JSON.parse(contentBuf.toString());
701
+ } catch (error) {
702
+ logger.error({ err: error, node }, "Failed to parse mex newsletter notification");
703
+ return;
704
+ }
705
+
706
+ const operation = content?.operation || payloadNode?.attrs?.op_name || node?.attrs?.op_name;
707
+ const linkedProfiles = content?.data?.[Types_1.XWAPathsMexUpdates.LINKED_PROFILES];
708
+ const updates = content?.updates || (linkedProfiles ? [linkedProfiles] : undefined);
709
+
710
+ if (operation === Types_1.MexUpdatesOperations.LINKED_PROFILES) {
711
+ const mappings = [];
712
+ for (const update of updates || []) {
713
+ const lid = normalizeOptionalJid(update?.jid);
714
+ const addedProfiles = Array.isArray(update?.added_profiles) ? update.added_profiles : [];
715
+ for (const profile of addedProfiles) {
716
+ const pn = normalizeOptionalJid(typeof profile === "string" ? profile : (profile?.pn || profile?.jid || ""));
717
+ if (lid && pn) {
718
+ const mapping = { lid, pn };
719
+ ev.emit("lid-mapping.update", mapping);
720
+ mappings.push(mapping);
721
+ }
722
+ }
723
+ }
724
+
725
+ if (mappings.length && signalRepository?.lidMapping?.storeLIDPNMappings) {
726
+ await signalRepository.lidMapping.storeLIDPNMappings(mappings);
727
+ }
728
+ if (mappings.length && signalRepository?.migrateSession) {
729
+ for (const mapping of mappings) {
730
+ await signalRepository.migrateSession(mapping.pn, mapping.lid);
731
+ }
732
+ }
733
+ return;
734
+ }
683
735
 
684
736
  let contentPath;
685
737
  let action;
@@ -777,7 +829,7 @@ const makeMessagesRecvSocket = (config) => {
777
829
  handleNewsletterNotification(node.attrs.from, child);
778
830
  break;
779
831
  case "mex":
780
- handleMexNotification(node.attrs.from, child);
832
+ await handleMexNotification(node.attrs.from, child);
781
833
  break;
782
834
  case "mediaretry":
783
835
  const event = Utils_1.decodeMediaRetryNode(node);
@@ -1635,13 +1687,19 @@ const makeMessagesRecvSocket = (config) => {
1635
1687
  // error in acknowledgement,
1636
1688
  // device could not display the message
1637
1689
  if (attrs.error) {
1690
+ const isReachoutTimelocked = attrs.error === String(Utils_1.NACK_REASONS.SenderReachoutTimelocked);
1691
+ if (isReachoutTimelocked && fetchAccountReachoutTimelock) {
1692
+ await fetchAccountReachoutTimelock().catch((err) =>
1693
+ logger.warn({ err }, "failed to fetch reachout timelock")
1694
+ );
1695
+ }
1638
1696
  logger.warn({ attrs }, "received error in ack");
1639
1697
  ev.emit("messages.update", [
1640
1698
  {
1641
1699
  key,
1642
1700
  update: {
1643
1701
  status: Types_1.WAMessageStatus.ERROR,
1644
- messageStubParameters: [attrs.error],
1702
+ messageStubParameters: isReachoutTimelocked ? [attrs.error, Utils_1.ACCOUNT_RESTRICTED_TEXT] : [attrs.error],
1645
1703
  },
1646
1704
  },
1647
1705
  ]);
@@ -170,4 +170,6 @@ export declare const makeMessagesSocket: (config: SocketConfig) => {
170
170
  requestPairingCode: (phoneNumber: string, code?: string) => Promise<string>
171
171
  waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>
172
172
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<BinaryNode>
173
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>
174
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>
173
175
  }
@@ -558,7 +558,7 @@ const makeMessagesSocket = (config) => {
558
558
  }
559
559
 
560
560
  const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, additionalNodes, AI = true }) => {
561
- const meId = authState.creds.me.id
561
+ const meId = Utils_1.assertMeId(authState.creds)
562
562
  const meLid = authState.creds.me?.lid
563
563
 
564
564
  let didPushAdditional = false
@@ -1534,4 +1534,4 @@ const makeMessagesSocket = (config) => {
1534
1534
 
1535
1535
  module.exports = {
1536
1536
  makeMessagesSocket
1537
- }
1537
+ }
@@ -147,6 +147,8 @@ export declare const makeNewsletterSocket: (config: SocketConfig) => {
147
147
  requestPairingCode: (phoneNumber: string, code?: string) => Promise<string>
148
148
  waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>
149
149
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<BinaryNode>
150
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>
151
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>
150
152
  }
151
153
 
152
154
  export declare const extractNewsletterMetadata: (node: BinaryNode, isCreate?: boolean) => NewsletterMetadata
@@ -40,6 +40,8 @@ export declare const makeSocket: (config: SocketConfig) => {
40
40
  /** Waits for the connection to WA to reach a state */
41
41
  waitForConnectionUpdate: (check: (u: Partial<import("../Types").ConnectionState>) => boolean | undefined, timeoutMs?: number | undefined) => Promise<void>
42
42
  sendWAMBuffer: (wamBuffer: Buffer) => Promise<BinaryNode>
43
+ fetchAccountReachoutTimelock: () => Promise<import("../Types").ReachoutTimelockState>
44
+ fetchNewChatMessageCap: () => Promise<import("../Types").NewChatMessageCapInfo>
43
45
  }
44
46
 
45
- export type Socket = ReturnType<typeof makeSocket>
47
+ export type Socket = ReturnType<typeof makeSocket>
@@ -15,6 +15,7 @@ const BinaryInfo_1 = require("../WAM/BinaryInfo")
15
15
  const USyncQuery_1 = require("../WAUSync/USyncQuery")
16
16
  const USyncUser_1 = require("../WAUSync/USyncUser")
17
17
  const Client_1 = require("./Client")
18
+ const mex_1 = require("./mex")
18
19
 
19
20
  /**
20
21
  * Connects to WA servers and performs:
@@ -690,6 +691,35 @@ const makeSocket = (config) => {
690
691
  ]
691
692
  })
692
693
  }
694
+
695
+ const fetchAccountReachoutTimelock = async () => {
696
+ const queryResult = await mex_1.executeWMexQuery(
697
+ {},
698
+ Types_1.QueryIds.REACHOUT_TIMELOCK,
699
+ Types_1.XWAPaths.REACHOUT_TIMELOCK,
700
+ query,
701
+ generateMessageTag
702
+ )
703
+ const result = {
704
+ isActive: !!queryResult?.is_active,
705
+ timeEnforcementEnds: queryResult?.time_enforcement_ends && queryResult.time_enforcement_ends !== '0'
706
+ ? new Date(parseInt(queryResult.time_enforcement_ends, 10) * 1000)
707
+ : undefined,
708
+ enforcementType: queryResult?.enforcement_type || Types_1.ReachoutTimelockEnforcementType.DEFAULT
709
+ }
710
+ ev.emit('connection.update', { reachoutTimeLock: result })
711
+ return result
712
+ }
713
+
714
+ const fetchNewChatMessageCap = async () => {
715
+ return mex_1.executeWMexQuery(
716
+ { input: { type: 'INDIVIDUAL_NEW_CHAT_MSG' } },
717
+ Types_1.QueryIds.MESSAGE_CAPPING_INFO,
718
+ Types_1.XWAPaths.MESSAGE_CAPPING_INFO,
719
+ query,
720
+ generateMessageTag
721
+ )
722
+ }
693
723
 
694
724
  ws.on('message', onMessageReceived)
695
725
 
@@ -934,6 +964,8 @@ const makeSocket = (config) => {
934
964
  /** Waits for the connection to WA to reach a state */
935
965
  waitForConnectionUpdate: Utils_1.bindWaitForConnectionUpdate(ev),
936
966
  sendWAMBuffer,
967
+ fetchAccountReachoutTimelock,
968
+ fetchNewChatMessageCap,
937
969
  executeUSyncQuery,
938
970
  onWhatsApp
939
971
  }
@@ -41,6 +41,10 @@ export type BaileysEventMap = {
41
41
  lid: string
42
42
  jid: string
43
43
  }
44
+ 'lid-mapping.update': {
45
+ lid: string
46
+ pn: string
47
+ }
44
48
  /** delete chats with given ID */
45
49
  'chats.delete': string[]
46
50
  /** presence of contact in a chat updated */
@@ -1,9 +1,11 @@
1
1
  export declare const enum MexUpdatesOperations {
2
2
  OWNER_COMMUNITY = "NotificationCommunityOwnerUpdate",
3
- GROUP_LIMIT_SHARING = "NotificationGroupLimitSharingPropertyUpdate"
3
+ GROUP_LIMIT_SHARING = "NotificationGroupLimitSharingPropertyUpdate",
4
+ LINKED_PROFILES = "NotificationLinkedProfilesUpdates"
4
5
  }
5
6
 
6
- export declare const enum XWAPathsUpdates {
7
+ export declare const enum XWAPathsMexUpdates {
7
8
  GROUP_SHARING_CHANGE = "xwa2_notify_group_on_prop_change",
8
- COMMUNITY_OWNER_CHANGE = "xwa2_notify_group_on_participants_roles_change"
9
- }
9
+ COMMUNITY_OWNER_CHANGE = "xwa2_notify_group_on_participants_roles_change",
10
+ LINKED_PROFILES = "xwa2_notify_linked_profiles"
11
+ }
@@ -3,16 +3,18 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true })
4
4
 
5
5
  const MexUpdatesOperations = {
6
- OWNER_COMMUNITY: "NotificationCommunityOwnerUpdate",
7
- GROUP_LIMIT_SHARING: "NotificationGroupLimitSharingPropertyUpdate"
6
+ OWNER_COMMUNITY: "NotificationCommunityOwnerUpdate",
7
+ GROUP_LIMIT_SHARING: "NotificationGroupLimitSharingPropertyUpdate",
8
+ LINKED_PROFILES: "NotificationLinkedProfilesUpdates"
8
9
  }
9
10
 
10
11
  const XWAPathsMexUpdates = {
11
- GROUP_SHARING_CHANGE: "xwa2_notify_group_on_prop_change",
12
- COMMUNITY_OWNER_CHANGE: "xwa2_notify_group_on_participants_roles_change"
12
+ GROUP_SHARING_CHANGE: "xwa2_notify_group_on_prop_change",
13
+ COMMUNITY_OWNER_CHANGE: "xwa2_notify_group_on_participants_roles_change",
14
+ LINKED_PROFILES: "xwa2_notify_linked_profiles"
13
15
  }
14
16
 
15
17
  module.exports = {
16
18
  MexUpdatesOperations,
17
19
  XWAPathsMexUpdates
18
- }
20
+ }
@@ -90,14 +90,18 @@ export declare const enum XWAPaths {
90
90
  CREATE = "xwa2_newsletter_create",
91
91
  NEWSLETTER = "xwa2_newsletter",
92
92
  SUBSCRIBED = "xwa2_newsletter_subscribed",
93
- METADATA_UPDATE = "xwa2_notify_newsletter_on_metadata_update"
93
+ METADATA_UPDATE = "xwa2_notify_newsletter_on_metadata_update",
94
+ JOIN_V2 = "xwa2_newsletter_join_v2",
95
+ LEAVE_V2 = "xwa2_newsletter_leave_v2",
96
+ REACHOUT_TIMELOCK = "xwa2_fetch_account_reachout_timelock",
97
+ MESSAGE_CAPPING_INFO = "xwa2_message_capping_info"
94
98
  }
95
99
 
96
100
  export declare const enum QueryIds {
97
101
  JOB_MUTATION = "7150902998257522",
98
102
  METADATA = "6620195908089573",
99
- UNFOLLOW = "7238632346214362",
100
- FOLLOW = "7871414976211147",
103
+ UNFOLLOW = "9767147403369991",
104
+ FOLLOW = "24404358912487870",
101
105
  UNMUTE = "7337137176362961",
102
106
  MUTE = "25151904754424642",
103
107
  CREATE = "6996806640408138",
@@ -105,5 +109,7 @@ export declare const enum QueryIds {
105
109
  CHANGE_OWNER = "7341777602580933",
106
110
  DELETE = "8316537688363079",
107
111
  DEMOTE = "6551828931592903",
108
- SUBSCRIBED = "6388546374527196"
109
- }
112
+ SUBSCRIBED = "6388546374527196",
113
+ REACHOUT_TIMELOCK = "23983697327930364",
114
+ MESSAGE_CAPPING_INFO = "24503548349331633"
115
+ }
@@ -15,14 +15,18 @@ const XWAPaths = {
15
15
  CREATE: "xwa2_newsletter_create",
16
16
  NEWSLETTER: "xwa2_newsletter",
17
17
  SUBSCRIBED: "xwa2_newsletter_subscribed",
18
- METADATA_UPDATE: "xwa2_notify_newsletter_on_metadata_update"
18
+ METADATA_UPDATE: "xwa2_notify_newsletter_on_metadata_update",
19
+ JOIN_V2: "xwa2_newsletter_join_v2",
20
+ LEAVE_V2: "xwa2_newsletter_leave_v2",
21
+ REACHOUT_TIMELOCK: "xwa2_fetch_account_reachout_timelock",
22
+ MESSAGE_CAPPING_INFO: "xwa2_message_capping_info"
19
23
  }
20
24
 
21
25
  const QueryIds = {
22
26
  JOB_MUTATION: "7150902998257522",
23
27
  METADATA: "6620195908089573",
24
- UNFOLLOW: "7238632346214362",
25
- FOLLOW: "7871414976211147",
28
+ UNFOLLOW: "9767147403369991",
29
+ FOLLOW: "24404358912487870",
26
30
  UNMUTE: "7337137176362961",
27
31
  MUTE: "25151904754424642",
28
32
  CREATE: "6996806640408138",
@@ -30,11 +34,13 @@ const QueryIds = {
30
34
  CHANGE_OWNER: "7341777602580933",
31
35
  DELETE: "8316537688363079",
32
36
  DEMOTE: "6551828931592903",
33
- SUBSCRIBED: "6388546374527196"
37
+ SUBSCRIBED: "6388546374527196",
38
+ REACHOUT_TIMELOCK: "23983697327930364",
39
+ MESSAGE_CAPPING_INFO: "24503548349331633"
34
40
  }
35
41
 
36
42
  module.exports = {
37
43
  MexOperations,
38
44
  XWAPaths,
39
45
  QueryIds
40
- }
46
+ }
@@ -38,4 +38,67 @@ export type ConnectionState = {
38
38
  * If this is false, the primary phone and other devices will receive notifs
39
39
  * */
40
40
  isOnline?: boolean
41
- }
41
+ /**
42
+ * When this is active, WhatsApp prevents outgoing messages and calls.
43
+ */
44
+ reachoutTimeLock?: ReachoutTimelockState
45
+ }
46
+
47
+ export type ReachoutTimelockState = {
48
+ isActive?: boolean
49
+ timeEnforcementEnds?: Date
50
+ enforcementType?: ReachoutTimelockEnforcementType
51
+ }
52
+
53
+ export declare const enum ReachoutTimelockEnforcementType {
54
+ BIZ_COMMERCE_VIOLATION_ALCOHOL = "BIZ_COMMERCE_VIOLATION_ALCOHOL",
55
+ BIZ_COMMERCE_VIOLATION_ADULT = "BIZ_COMMERCE_VIOLATION_ADULT",
56
+ BIZ_COMMERCE_VIOLATION_ANIMALS = "BIZ_COMMERCE_VIOLATION_ANIMALS",
57
+ BIZ_COMMERCE_VIOLATION_BODY_PARTS_FLUIDS = "BIZ_COMMERCE_VIOLATION_BODY_PARTS_FLUIDS",
58
+ BIZ_COMMERCE_VIOLATION_DATING = "BIZ_COMMERCE_VIOLATION_DATING",
59
+ BIZ_COMMERCE_VIOLATION_DIGITAL_SERVICES_PRODUCTS = "BIZ_COMMERCE_VIOLATION_DIGITAL_SERVICES_PRODUCTS",
60
+ BIZ_COMMERCE_VIOLATION_DRUGS = "BIZ_COMMERCE_VIOLATION_DRUGS",
61
+ BIZ_COMMERCE_VIOLATION_DRUGS_ONLY_OTC = "BIZ_COMMERCE_VIOLATION_DRUGS_ONLY_OTC",
62
+ BIZ_COMMERCE_VIOLATION_GAMBLING = "BIZ_COMMERCE_VIOLATION_GAMBLING",
63
+ BIZ_COMMERCE_VIOLATION_HEALTHCARE = "BIZ_COMMERCE_VIOLATION_HEALTHCARE",
64
+ BIZ_COMMERCE_VIOLATION_REAL_FAKE_CURRENCY = "BIZ_COMMERCE_VIOLATION_REAL_FAKE_CURRENCY",
65
+ BIZ_COMMERCE_VIOLATION_SUPPLEMENTS = "BIZ_COMMERCE_VIOLATION_SUPPLEMENTS",
66
+ BIZ_COMMERCE_VIOLATION_TOBACCO = "BIZ_COMMERCE_VIOLATION_TOBACCO",
67
+ BIZ_COMMERCE_VIOLATION_VIOLENT_CONTENT = "BIZ_COMMERCE_VIOLATION_VIOLENT_CONTENT",
68
+ BIZ_COMMERCE_VIOLATION_WEAPONS = "BIZ_COMMERCE_VIOLATION_WEAPONS",
69
+ BIZ_QUALITY = "BIZ_QUALITY",
70
+ DEFAULT = "DEFAULT",
71
+ WEB_COMPANION_ONLY = "WEB_COMPANION_ONLY"
72
+ }
73
+
74
+ export declare const enum NewChatMessageCappingStatusType {
75
+ NONE = "NONE",
76
+ FIRST_WARNING = "FIRST_WARNING",
77
+ SECOND_WARNING = "SECOND_WARNING",
78
+ CAPPED = "CAPPED"
79
+ }
80
+
81
+ export declare const enum NewChatMessageCappingMVStatusType {
82
+ NOT_ELIGIBLE = "NOT_ELIGIBLE",
83
+ NOT_ACTIVE = "NOT_ACTIVE",
84
+ ACTIVE = "ACTIVE",
85
+ ACTIVE_UPGRADE_AVAILABLE = "ACTIVE_UPGRADE_AVAILABLE"
86
+ }
87
+
88
+ export declare const enum NewChatMessageCappingOTEStatusType {
89
+ NOT_ELIGIBLE = "NOT_ELIGIBLE",
90
+ ELIGIBLE = "ELIGIBLE",
91
+ ACTIVE_IN_CURRENT_CYCLE = "ACTIVE_IN_CURRENT_CYCLE",
92
+ EXHAUSTED = "EXHAUSTED"
93
+ }
94
+
95
+ export type NewChatMessageCapInfo = {
96
+ total_quota?: number
97
+ used_quota?: number
98
+ cycle_start_timestamp?: string
99
+ cycle_end_timestamp?: string
100
+ server_sent_timestamp?: string
101
+ ote_status?: NewChatMessageCappingOTEStatusType
102
+ mv_status?: NewChatMessageCappingMVStatusType
103
+ capping_status?: NewChatMessageCappingStatusType
104
+ }
@@ -9,6 +9,52 @@ const SyncState = {
9
9
  Online: 3
10
10
  }
11
11
 
12
+ const ReachoutTimelockEnforcementType = {
13
+ BIZ_COMMERCE_VIOLATION_ALCOHOL: "BIZ_COMMERCE_VIOLATION_ALCOHOL",
14
+ BIZ_COMMERCE_VIOLATION_ADULT: "BIZ_COMMERCE_VIOLATION_ADULT",
15
+ BIZ_COMMERCE_VIOLATION_ANIMALS: "BIZ_COMMERCE_VIOLATION_ANIMALS",
16
+ BIZ_COMMERCE_VIOLATION_BODY_PARTS_FLUIDS: "BIZ_COMMERCE_VIOLATION_BODY_PARTS_FLUIDS",
17
+ BIZ_COMMERCE_VIOLATION_DATING: "BIZ_COMMERCE_VIOLATION_DATING",
18
+ BIZ_COMMERCE_VIOLATION_DIGITAL_SERVICES_PRODUCTS: "BIZ_COMMERCE_VIOLATION_DIGITAL_SERVICES_PRODUCTS",
19
+ BIZ_COMMERCE_VIOLATION_DRUGS: "BIZ_COMMERCE_VIOLATION_DRUGS",
20
+ BIZ_COMMERCE_VIOLATION_DRUGS_ONLY_OTC: "BIZ_COMMERCE_VIOLATION_DRUGS_ONLY_OTC",
21
+ BIZ_COMMERCE_VIOLATION_GAMBLING: "BIZ_COMMERCE_VIOLATION_GAMBLING",
22
+ BIZ_COMMERCE_VIOLATION_HEALTHCARE: "BIZ_COMMERCE_VIOLATION_HEALTHCARE",
23
+ BIZ_COMMERCE_VIOLATION_REAL_FAKE_CURRENCY: "BIZ_COMMERCE_VIOLATION_REAL_FAKE_CURRENCY",
24
+ BIZ_COMMERCE_VIOLATION_SUPPLEMENTS: "BIZ_COMMERCE_VIOLATION_SUPPLEMENTS",
25
+ BIZ_COMMERCE_VIOLATION_TOBACCO: "BIZ_COMMERCE_VIOLATION_TOBACCO",
26
+ BIZ_COMMERCE_VIOLATION_VIOLENT_CONTENT: "BIZ_COMMERCE_VIOLATION_VIOLENT_CONTENT",
27
+ BIZ_COMMERCE_VIOLATION_WEAPONS: "BIZ_COMMERCE_VIOLATION_WEAPONS",
28
+ BIZ_QUALITY: "BIZ_QUALITY",
29
+ DEFAULT: "DEFAULT",
30
+ WEB_COMPANION_ONLY: "WEB_COMPANION_ONLY"
31
+ }
32
+
33
+ const NewChatMessageCappingStatusType = {
34
+ NONE: "NONE",
35
+ FIRST_WARNING: "FIRST_WARNING",
36
+ SECOND_WARNING: "SECOND_WARNING",
37
+ CAPPED: "CAPPED"
38
+ }
39
+
40
+ const NewChatMessageCappingMVStatusType = {
41
+ NOT_ELIGIBLE: "NOT_ELIGIBLE",
42
+ NOT_ACTIVE: "NOT_ACTIVE",
43
+ ACTIVE: "ACTIVE",
44
+ ACTIVE_UPGRADE_AVAILABLE: "ACTIVE_UPGRADE_AVAILABLE"
45
+ }
46
+
47
+ const NewChatMessageCappingOTEStatusType = {
48
+ NOT_ELIGIBLE: "NOT_ELIGIBLE",
49
+ ELIGIBLE: "ELIGIBLE",
50
+ ACTIVE_IN_CURRENT_CYCLE: "ACTIVE_IN_CURRENT_CYCLE",
51
+ EXHAUSTED: "EXHAUSTED"
52
+ }
53
+
12
54
  module.exports = {
13
- SyncState
14
- }
55
+ SyncState,
56
+ ReachoutTimelockEnforcementType,
57
+ NewChatMessageCappingStatusType,
58
+ NewChatMessageCappingMVStatusType,
59
+ NewChatMessageCappingOTEStatusType
60
+ }
@@ -18,4 +18,6 @@ export declare function makeCacheableSignalKeyStore(store: SignalKeyStore, logge
18
18
  */
19
19
  export declare const addTransactionCapability: (state: SignalKeyStore, logger?: ILogger, { maxCommitRetries, delayBetweenTriesMs }: TransactionCapabilityOptions) => SignalKeyStoreWithTransaction
20
20
 
21
- export declare const initAuthCreds: () => AuthenticationCreds
21
+ export declare const assertMeId: (creds: AuthenticationCreds) => string
22
+
23
+ export declare const initAuthCreds: () => AuthenticationCreds
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "__esModule", { value: true })
8
8
 
9
9
  const crypto_1 = require("crypto")
10
10
  const node_cache_1 = __importDefault(require("@cacheable/node-cache"))
11
+ const boom_1 = require("@hapi/boom")
11
12
  const Defaults_1 = require("../Defaults")
12
13
  const crypto_2 = require("./crypto")
13
14
  const generics_1 = require("./generics")
@@ -175,6 +176,15 @@ const addTransactionCapability = (state, logger, { maxCommitRetries, delayBetwee
175
176
  }
176
177
  }
177
178
 
179
+ const assertMeId = (creds) => {
180
+ const id = creds.me?.id
181
+ if (!id) {
182
+ throw new boom_1.Boom('Cannot proceed: socket is not authenticated yet (creds.me.id is missing)', { statusCode: 401 })
183
+ }
184
+
185
+ return id
186
+ }
187
+
178
188
  const initAuthCreds = () => {
179
189
  const identityKey = crypto_2.Curve.generateKeyPair()
180
190
  return {
@@ -201,5 +211,6 @@ const initAuthCreds = () => {
201
211
  module.exports = {
202
212
  makeCacheableSignalKeyStore,
203
213
  addTransactionCapability,
214
+ assertMeId,
204
215
  initAuthCreds
205
- }
216
+ }
@@ -7,7 +7,10 @@ export declare const NO_MESSAGE_FOUND_ERROR_TEXT = "Message absent from node"
7
7
 
8
8
  export declare const MISSING_KEYS_ERROR_TEXT = "Key used already or never filled"
9
9
 
10
+ export declare const ACCOUNT_RESTRICTED_TEXT = "Your account has been restricted"
11
+
10
12
  export declare const NACK_REASONS: {
13
+ SenderReachoutTimelocked: number
11
14
  ParsingError: number
12
15
  UnrecognizedStanza: number
13
16
  UnrecognizedStanzaClass: number
@@ -38,4 +41,4 @@ export declare const decryptMessageNode: (stanza: BinaryNode, meId: string, meLi
38
41
  category: string
39
42
  author: string
40
43
  decrypt(): Promise<void>
41
- }
44
+ }
@@ -12,7 +12,10 @@ const NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node'
12
12
 
13
13
  const MISSING_KEYS_ERROR_TEXT = 'Key used already or never filled'
14
14
 
15
+ const ACCOUNT_RESTRICTED_TEXT = 'Your account has been restricted'
16
+
15
17
  const NACK_REASONS = {
18
+ SenderReachoutTimelocked: 463,
16
19
  ParsingError: 487,
17
20
  UnrecognizedStanza: 488,
18
21
  UnrecognizedStanzaClass: 489,
@@ -43,6 +46,14 @@ function decodeMessageNode(stanza, meId, meLid) {
43
46
  participant = stanza.attrs.participant_pn;
44
47
  }
45
48
  const recipient = stanza.attrs.recipient
49
+ if (!msgId) {
50
+ throw new boom_1.Boom('Invalid message stanza: missing id attribute', { data: stanza })
51
+ }
52
+
53
+ if (!from) {
54
+ throw new boom_1.Boom('Invalid message stanza: missing from attribute', { data: stanza })
55
+ }
56
+
46
57
  const isMe = (jid) => WABinary_1.areJidsSameUser(jid, meId)
47
58
  const isMeLid = (jid) => WABinary_1.areJidsSameUser(jid, meLid)
48
59
  if (WABinary_1.isJidUser(from)) {
@@ -287,6 +298,10 @@ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
287
298
  }
288
299
 
289
300
  module.exports = {
301
+ NO_MESSAGE_FOUND_ERROR_TEXT,
302
+ MISSING_KEYS_ERROR_TEXT,
303
+ ACCOUNT_RESTRICTED_TEXT,
304
+ NACK_REASONS,
290
305
  decodeMessageNode,
291
306
  decryptMessageNode
292
307
  }
@@ -1555,7 +1555,7 @@ const patchMessageForMdIfRequired = (message) => {
1555
1555
  if (message?.buttonsMessage ||
1556
1556
  message?.templateMessage ||
1557
1557
  message?.listMessage ||
1558
- message?.interactiveMessage?.nativeFlowMesaage
1558
+ message?.interactiveMessage
1559
1559
  ) {
1560
1560
  message = {
1561
1561
  viewOnceMessageV2Extension: {
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true })
4
4
 
5
5
  const WAProto_1 = require("../../WAProto")
6
+ const boom_1 = require("@hapi/boom")
6
7
  const Types_1 = require("../Types")
7
8
  const messages_1 = require("../Utils/messages")
8
9
  const WABinary_1 = require("../WABinary")
@@ -80,9 +81,21 @@ const shouldIncrementChatUnread = (message) => !message.key.fromMe && !message.m
80
81
  * Typically -- that'll be the remoteJid, but for broadcasts, it'll be the participant
81
82
  */
82
83
  const getChatId = ({ remoteJid, participant, fromMe }) => {
84
+ if (!remoteJid) {
85
+ throw new boom_1.Boom('Cannot derive chat id: message key is missing remoteJid', {
86
+ data: { remoteJid, participant, fromMe }
87
+ })
88
+ }
89
+
83
90
  if (WABinary_1.isJidBroadcast(remoteJid)
84
91
  && !WABinary_1.isJidStatusBroadcast(remoteJid)
85
92
  && !fromMe) {
93
+ if (!participant) {
94
+ throw new boom_1.Boom('Cannot derive chat id: broadcast message key is missing participant', {
95
+ data: { remoteJid, fromMe }
96
+ })
97
+ }
98
+
86
99
  return participant
87
100
  }
88
101
  return remoteJid
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neelegirly/baileys",
3
- "version": "2.2.20",
3
+ "version": "2.2.21",
4
4
  "description": "Neelegirly fork of Baileys: multi-device WhatsApp Web API for Node.js",
5
5
  "keywords": [
6
6
  "whatsapp",
@@ -43,7 +43,7 @@
43
43
  "@adiwajshing/keyed-db": "^0.2.4",
44
44
  "@cacheable/node-cache": "^1.5.4",
45
45
  "@hapi/boom": "^9.1.3",
46
- "@neelegirly/libsignal": "1.0.29",
46
+ "@neelegirly/libsignal": "1.0.30",
47
47
  "async-mutex": "^0.5.0",
48
48
  "audio-decode": "^2.1.3",
49
49
  "axios": "^1.3.3",
@@ -58,7 +58,7 @@
58
58
  "ws": "^8.13.0"
59
59
  },
60
60
  "overrides": {
61
- "@neelegirly/libsignal": "1.0.29"
61
+ "@neelegirly/libsignal": "1.0.30"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@adiwajshing/eslint-config": "github:adiwajshing/eslint-config",