@neelegirl/baileys 2.1.7 → 2.1.9

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
@@ -3,7 +3,7 @@
3
3
  # @neelegirl/baileys
4
4
 
5
5
  ### CommonJS WhatsApp Web runtime for Neelegirl projects
6
- ### Conservative merge strategy based on WhiskeySockets/Baileys
6
+ ### Conservative merge strategy based on WhiskeySockets/Baileys with QR, pairing, and LID/libsignal maintenance
7
7
 
8
8
  [![npm version](https://img.shields.io/npm/v/@neelegirl/baileys?style=for-the-badge&color=ff69b4&logo=npm)](https://www.npmjs.com/package/@neelegirl/baileys)
9
9
  [![node](https://img.shields.io/badge/node-%3E%3D20-2ea043?style=for-the-badge&logo=node.js)](https://nodejs.org)
@@ -19,7 +19,7 @@
19
19
 
20
20
  | Package | Version | Main goal |
21
21
  |---|---:|---|
22
- | `@neelegirl/baileys` | `2.1.7` | Stable Neelegirl fork with preserved project-specific runtime behavior |
22
+ | `@neelegirl/baileys` | `2.1.9` | Stable Neelegirl fork with preserved project-specific runtime behavior |
23
23
 
24
24
  [Installation](#installation) · [Quickstart](#quickstart) · [Protected logic](#protected-logic) · [Device and LID notes](#device-and-lid-notes) · [Verified exports](#verified-exports) · [Release notes](#release-notes)
25
25
 
@@ -30,9 +30,10 @@
30
30
  ## Table of Contents
31
31
 
32
32
  - [Overview](#overview)
33
+ - [Stack relationship](#stack-relationship)
33
34
  - [Why this fork exists](#why-this-fork-exists)
34
35
  - [Protected logic](#protected-logic)
35
- - [What was updated in 2.1.6](#what-was-updated-in-216)
36
+ - [What was updated in 2.1.9](#what-was-updated-in-219)
36
37
  - [Installation](#installation)
37
38
  - [Imports](#imports)
38
39
  - [Quickstart](#quickstart)
@@ -50,13 +51,31 @@
50
51
 
51
52
  `@neelegirl/baileys` is the local CommonJS-oriented Neelegirl fork of Baileys used in this stack. It is meant to keep existing Neelegirl-specific behavior stable while still absorbing compatible fixes from the public WhiskeySockets/Baileys project where that improves correctness.
52
53
 
53
- This package was rechecked against the public WhiskeySockets/Baileys repository on `2026-03-19`. The merge strategy is conservative by design:
54
+ This package was rechecked against the public WhiskeySockets/Baileys repository and the repaired local source package on `2026-03-20`. The merge strategy is conservative by design:
54
55
 
55
56
  - keep working Neelegirl runtime behavior
56
57
  - adopt compatible fixes
57
58
  - avoid blind upstream replacement
58
59
  - avoid destructive refactors in project-critical paths
59
60
 
61
+ ## Stack relationship
62
+
63
+ This fork sits in the middle of the local Neelegirl WhatsApp stack.
64
+
65
+ | Package | Role | Why it matters here |
66
+ |---|---|---|
67
+ | `@neelegirl/baileys` | WhatsApp Web runtime and socket layer | Owns QR, pairing, events, message send/recv, device handling |
68
+ | `@neelegirl/libsignal` | Signal session and identity runtime | Owns session cipher state, identity keys, and LID-aware session migration helpers |
69
+ | `@neelegirl/wa-api` | Convenience wrapper | Wraps the socket for multi-session management and simpler app integration |
70
+
71
+ The recent maintenance pass specifically verified that the Baileys socket layer and the local libsignal-facing repository agree again on:
72
+
73
+ - pairing-code platform handling for WhatsApp Web-style flows
74
+ - LID-to-PN mapping storage
75
+ - session migration helpers
76
+ - history-sync mapping capture
77
+ - conservative JID and device normalization
78
+
60
79
  ## Why this fork exists
61
80
 
62
81
  The local package differs from upstream for practical reasons:
@@ -77,12 +96,31 @@ The following logic was explicitly treated as protected during maintenance:
77
96
  - QR-code generation and QR lifecycle
78
97
  - `NEELE` message-ID generation and related custom handling
79
98
  - existing Neelegirl branding and log output
99
+ - existing WhatsApp Web / browser-specific pairing behavior
80
100
  - existing device, watch, and platform-specific behavior
81
101
  - existing custom community and message-stub handling
82
102
  - existing message-type behavior for conversation, extended text, media, and context handling
83
103
 
84
104
  Nothing in those areas was blindly replaced with upstream code.
85
105
 
106
+ ## What was updated in 2.1.9
107
+
108
+ ### Runtime hotfixes
109
+
110
+ - fixed hosted device `99` migration so PN sessions move into `@hosted.lid` instead of an invalid plain `@lid` target
111
+ - fixed hosted PN session lookup during PN to LID migration by resolving the actual Signal address key instead of assuming the plain PN key shape
112
+ - fixed `lru-cache` compatibility so the local CommonJS build works with both direct-class and named-export variants
113
+ - unblocked `LIDMappingStore` initialization during real bot startup
114
+ - unblocked the migrated session cache and retry caches that rely on the same constructor shape
115
+ - kept QR flow, `NEELE` message-ID logic, and project-specific device/watch handling untouched
116
+
117
+ ### Verified after the hotfix
118
+
119
+ - hosted device `99` mock migrations now land on `hosted.lid` Signal addresses and no longer get skipped
120
+ - multi-session startup completed successfully in the local Neelegirl runtime
121
+ - LID/device watch output continued to work after the patch
122
+ - the package now starts without the `LRUCache is not a constructor` crash seen before this release
123
+
86
124
  ## What was updated in 2.1.6
87
125
 
88
126
  ### Runtime compatibility
@@ -400,6 +438,8 @@ const result = transferDevice(
400
438
  )
401
439
  ```
402
440
 
441
+ When the source JID is a hosted device such as `491234567890:99@hosted`, the helper now keeps that hosted device space and returns `1234567890:99@hosted.lid`.
442
+
403
443
  ### Why this matters here
404
444
 
405
445
  Neelegirl-specific code in this package already relies on richer identity handling around:
@@ -1614,6 +1654,18 @@ This README is intentionally longer than a minimal package page because users of
1614
1654
 
1615
1655
  ## Release notes
1616
1656
 
1657
+ ### 2.1.9
1658
+
1659
+ - fixed hosted device `99` PN to LID migration so the runtime keeps `hosted` and `hosted.lid` identity space correctly
1660
+ - fixed Signal session lookup for hosted PN sessions during migration by using the real session-address encoding
1661
+ - README and package metadata refreshed to match the current stabilized runtime
1662
+
1663
+ ### 2.1.8
1664
+
1665
+ - runtime hotfix release for CommonJS `lru-cache` compatibility in the current Neelegirl environment
1666
+ - fixed constructor resolution used by LID mapping and retry cache initialization
1667
+ - dependency range aligned to `@neelegirl/libsignal@^1.0.12`
1668
+
1617
1669
  ### 2.1.7
1618
1670
 
1619
1671
  - documentation expansion release
@@ -4,7 +4,8 @@ Object.defineProperty(exports, "__esModule", { value: true })
4
4
 
5
5
  const libsignal = require("@neelegirl/libsignal")
6
6
  const { PreKeyWhisperMessage } = require("@neelegirl/libsignal/src/protobufs")
7
- const { LRUCache } = require("lru-cache")
7
+ const LRUCacheModule = require("lru-cache")
8
+ const LRUCache = LRUCacheModule.LRUCache || LRUCacheModule
8
9
  const WASignalGroup_1 = require("./WASignalGroup")
9
10
  const lid_mapping_1 = require("./lid-mapping")
10
11
  const Utils_1 = require("../Utils")
@@ -174,27 +175,18 @@ function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
174
175
  if (!userDevices.includes(fromDeviceStr)) {
175
176
  userDevices.push(fromDeviceStr)
176
177
  }
177
- const uncachedDevices = userDevices.filter(device => !migratedSessionCache.has(`${user}.${device}`))
178
- const deviceSessionKeys = uncachedDevices.map(device => `${user}.${device}`)
178
+ const uncachedDeviceJids = userDevices
179
+ .map(device => {
180
+ const deviceNum = parseInt(device, 10)
181
+ const normalizedDevice = Number.isNaN(deviceNum) ? 0 : deviceNum
182
+ return `${user}${normalizedDevice ? `:${normalizedDevice}` : ''}@${normalizedDevice === 99 ? 'hosted' : 's.whatsapp.net'}`
183
+ })
184
+ .filter(jid => !migratedSessionCache.has(jidToSignalProtocolAddress(jid).toString()))
185
+ const deviceSessionKeys = uncachedDeviceJids.map(jid => jidToSignalProtocolAddress(jid).toString())
179
186
  const existingSessions = deviceSessionKeys.length
180
187
  ? await parsedKeys.get('session', deviceSessionKeys)
181
188
  : {}
182
- const deviceJids = []
183
- for (const [sessionKey, sessionData] of Object.entries(existingSessions)) {
184
- if (!sessionData) {
185
- continue
186
- }
187
- const deviceStr = sessionKey.split('.')[1]
188
- if (!deviceStr) {
189
- continue
190
- }
191
- const deviceNum = parseInt(deviceStr, 10)
192
- let jid = `${user}${deviceNum ? `:${deviceNum}` : ''}@s.whatsapp.net`
193
- if (deviceNum === 99) {
194
- jid = `${user}:99@hosted`
195
- }
196
- deviceJids.push(jid)
197
- }
189
+ const deviceJids = uncachedDeviceJids.filter(jid => existingSessions[jidToSignalProtocolAddress(jid).toString()])
198
190
  return parsedKeys.transaction(async () => {
199
191
  const migrationOps = deviceJids.map(jid => {
200
192
  const lidWithDevice = (0, WABinary_1.transferDevice)(jid, toJid)
@@ -234,7 +226,7 @@ function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
234
226
  await parsedKeys.set({ session: sessionUpdates })
235
227
  for (const op of migrationOps) {
236
228
  if (sessionUpdates[op.toAddr.toString()] && op.pnUser) {
237
- migratedSessionCache.set(`${op.pnUser}.${op.deviceId}`, true)
229
+ migratedSessionCache.set(op.fromAddr.toString(), true)
238
230
  }
239
231
  }
240
232
  }
@@ -2,7 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, "__esModule", { value: true })
4
4
 
5
- const { LRUCache } = require("lru-cache")
5
+ const LRUCacheModule = require("lru-cache")
6
+ const LRUCache = LRUCacheModule.LRUCache || LRUCacheModule
6
7
  const WABinary_1 = require("../WABinary")
7
8
 
8
9
  class LIDMappingStore {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MessageRetryManager = void 0;
4
4
  const lru_cache_1 = require("lru-cache");
5
+ const LRUCache = lru_cache_1.LRUCache || lru_cache_1;
5
6
  /** Number of sent messages to cache in memory for handling retry receipts */
6
7
  const RECENT_MESSAGES_SIZE = 512;
7
8
  const MESSAGE_KEY_SEPARATOR = '\u0000';
@@ -11,7 +12,7 @@ const PHONE_REQUEST_DELAY = 3000;
11
12
  class MessageRetryManager {
12
13
  constructor(logger, maxMsgRetryCount) {
13
14
  this.logger = logger;
14
- this.recentMessagesMap = new lru_cache_1.LRUCache({
15
+ this.recentMessagesMap = new LRUCache({
15
16
  max: RECENT_MESSAGES_SIZE,
16
17
  ttl: 5 * 60 * 1000,
17
18
  ttlAutopurge: true,
@@ -24,11 +25,11 @@ class MessageRetryManager {
24
25
  }
25
26
  });
26
27
  this.messageKeyIndex = new Map();
27
- this.sessionRecreateHistory = new lru_cache_1.LRUCache({
28
+ this.sessionRecreateHistory = new LRUCache({
28
29
  ttl: RECREATE_SESSION_TIMEOUT * 2,
29
30
  ttlAutopurge: true
30
31
  });
31
- this.retryCounters = new lru_cache_1.LRUCache({
32
+ this.retryCounters = new LRUCache({
32
33
  ttl: 15 * 60 * 1000,
33
34
  ttlAutopurge: true,
34
35
  updateAgeOnGet: true
@@ -176,4 +177,3 @@ exports.MessageRetryManager = MessageRetryManager;
176
177
  //# sourceMappingURL=message-retry-manager.js.map
177
178
 
178
179
 
179
-
@@ -113,10 +113,22 @@ const transferDevice = (fromJid, toJid) => {
113
113
  const fromDecoded = jidDecode(fromJid)
114
114
  const deviceId = fromDecoded?.device || 0
115
115
  const toDecoded = jidDecode(toJid)
116
- if (!toDecoded) {
116
+ if (!toDecoded?.user) {
117
117
  throw new Error(`invalid jid for device transfer: ${toJid}`)
118
118
  }
119
- return jidEncode(toDecoded.user, toDecoded.server, deviceId)
119
+ let server = toDecoded.server
120
+ const isHostedDevice = fromDecoded?.server === 'hosted'
121
+ || fromDecoded?.server === 'hosted.lid'
122
+ || deviceId === 99
123
+ if (isHostedDevice) {
124
+ if (server === 's.whatsapp.net') {
125
+ server = 'hosted'
126
+ }
127
+ else if (server === 'lid') {
128
+ server = 'hosted.lid'
129
+ }
130
+ }
131
+ return jidEncode(toDecoded.user, server, deviceId)
120
132
  }
121
133
 
122
134
  module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neelegirl/baileys",
3
- "version": "2.1.7",
3
+ "version": "2.1.9",
4
4
  "description": "CommonJS Neelegirl Baileys fork with preserved QR/NEELE logic and selective WhiskeySockets/Baileys compatibility updates",
5
5
  "keywords": [
6
6
  "whatsapp",
@@ -29,9 +29,9 @@
29
29
  "main": "lib/index.js",
30
30
  "types": "lib/index.d.ts",
31
31
  "files": [
32
- "lib/**/*",
33
- "WAProto/**/*",
34
- "engine-requirements.js"
32
+ "lib/*",
33
+ "WAProto/*",
34
+ "WASignalGroup/*.js"
35
35
  ],
36
36
  "scripts": {
37
37
  "build:all": "tsc && typedoc",
@@ -44,7 +44,7 @@
44
44
  "@adiwajshing/keyed-db": "^0.2.4",
45
45
  "@cacheable/node-cache": "^1.5.4",
46
46
  "@hapi/boom": "^9.1.3",
47
- "@neelegirl/libsignal": "^1.0.11",
47
+ "@neelegirl/libsignal": "^1.0.12",
48
48
  "async-mutex": "^0.5.0",
49
49
  "audio-decode": "^2.1.3",
50
50
  "axios": "^1.3.3",
@@ -69,7 +69,7 @@
69
69
  "conventional-changelog-cli": "^2.2.2",
70
70
  "eslint": "^8.0.0",
71
71
  "jest": "^27.0.6",
72
- "jimp": "^0.16.13",
72
+ "jimp": "^0.16.13",
73
73
  "json": "^11.0.0",
74
74
  "link-preview-js": "^3.0.5",
75
75
  "open": "^8.4.2",
@@ -89,9 +89,6 @@
89
89
  "sharp": "^0.32.6"
90
90
  },
91
91
  "peerDependenciesMeta": {
92
- "audio-decode": {
93
- "optional": true
94
- },
95
92
  "jimp": {
96
93
  "optional": true
97
94
  },
@@ -1,10 +0,0 @@
1
- const major = parseInt(process.versions.node.split('.')[0], 10);
2
-
3
- if (major < 20) {
4
- console.error(
5
- `\n❌ This package requires Node.js 20+ to run reliably.\n` +
6
- ` You are using Node.js ${process.versions.node}.\n` +
7
- ` Please upgrade to Node.js 20+ to proceed.\n`
8
- );
9
- process.exit(1);
10
- }