@aunucore/baileys 1.0.79 → 1.0.80
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/lib/Socket/index.js +26 -0
- package/lib/Utils/bounded-cache.js +22 -5
- package/lib/Utils/lid-store.js +21 -2
- package/lib/Utils/sent-message-cache.js +10 -2
- package/lib/Utils/signal.js +13 -0
- package/package.json +1 -1
package/lib/Socket/index.js
CHANGED
|
@@ -25,6 +25,32 @@ const makeWASocket = (config) => {
|
|
|
25
25
|
...DEFAULT_CONNECTION_CONFIG.transactionOpts,
|
|
26
26
|
...(config?.transactionOpts ?? {})
|
|
27
27
|
};
|
|
28
|
+
// AunuBaileys (1.0.80, HB-139 + HB-174 + addendum HB-139): the
|
|
29
|
+
// numeric connection config was spread raw above — an explicit
|
|
30
|
+
// undefined/NaN from the host (classically `Number(env.X)` of an
|
|
31
|
+
// unset variable) silently replaced the defaults, and every
|
|
32
|
+
// failure mode is silent: promiseTimeout(NaN) never settles (a
|
|
33
|
+
// half-open socket hangs forever), a NaN/0/negative
|
|
34
|
+
// keepAliveIntervalMs collapses setInterval to 1 ms (~850 ping
|
|
35
|
+
// IQs per second, and the dead-connection watchdog compares
|
|
36
|
+
// against NaN so it never fires), and a NaN/Infinity
|
|
37
|
+
// maxMsgRetryCount breaks both retry gates in opposite
|
|
38
|
+
// directions at once (retry receipts never capped, resends
|
|
39
|
+
// never sent). Sanitise once, here at the boundary: timeouts
|
|
40
|
+
// and intervals must be positive finite (else the documented
|
|
41
|
+
// default), the retry count must be finite (else the default),
|
|
42
|
+
// and qrTimeout — which has no Defaults entry (genPairQR falls
|
|
43
|
+
// back with `|| 60000` / `|| 20000`) — must be positive finite
|
|
44
|
+
// or absent (a negative value is truthy and would expire every
|
|
45
|
+
// QR instantly).
|
|
46
|
+
const positiveFiniteOr = (value, fallback) => (Number.isFinite(value) && value > 0 ? value : fallback);
|
|
47
|
+
newConfig.connectTimeoutMs = positiveFiniteOr(newConfig.connectTimeoutMs, DEFAULT_CONNECTION_CONFIG.connectTimeoutMs);
|
|
48
|
+
newConfig.defaultQueryTimeoutMs = positiveFiniteOr(newConfig.defaultQueryTimeoutMs, DEFAULT_CONNECTION_CONFIG.defaultQueryTimeoutMs);
|
|
49
|
+
newConfig.keepAliveIntervalMs = positiveFiniteOr(newConfig.keepAliveIntervalMs, DEFAULT_CONNECTION_CONFIG.keepAliveIntervalMs);
|
|
50
|
+
newConfig.maxMsgRetryCount = Number.isFinite(newConfig.maxMsgRetryCount) ? newConfig.maxMsgRetryCount : DEFAULT_CONNECTION_CONFIG.maxMsgRetryCount;
|
|
51
|
+
if (newConfig.qrTimeout !== undefined && !(Number.isFinite(newConfig.qrTimeout) && newConfig.qrTimeout > 0)) {
|
|
52
|
+
newConfig.qrTimeout = undefined;
|
|
53
|
+
}
|
|
28
54
|
// If the user hasn't provided their own history sync function,
|
|
29
55
|
// let's create a default one that respects the syncFullHistory flag.
|
|
30
56
|
if (config.shouldSyncHistoryMessage === undefined) {
|
|
@@ -13,7 +13,15 @@
|
|
|
13
13
|
* the receive path uses.
|
|
14
14
|
*/
|
|
15
15
|
export const makeBoundedTTLCache = ({ ttlSeconds = 3600, maxEntries = 1000 } = {}) => {
|
|
16
|
-
|
|
16
|
+
// AunuBaileys (1.0.80, HB-145): NaN/Infinity config defeated
|
|
17
|
+
// both bounds — `size > NaN` is always false (no eviction,
|
|
18
|
+
// ever) and a NaN ttlMs made expiresAt NaN, which never
|
|
19
|
+
// compares <= now, so entries lived forever. Sanitise at the
|
|
20
|
+
// boundary: finite values keep their exact meaning (counts
|
|
21
|
+
// are floored and clamped at 0), non-finite values fall back
|
|
22
|
+
// to the documented defaults (3600 s / 1000 entries).
|
|
23
|
+
const ttlMs = Number.isFinite(ttlSeconds) ? Math.max(1, ttlSeconds * 1000) : 3600 * 1000;
|
|
24
|
+
const limit = Number.isFinite(maxEntries) ? Math.max(0, Math.floor(maxEntries)) : 1000;
|
|
17
25
|
const map = new Map();
|
|
18
26
|
return {
|
|
19
27
|
get(key) {
|
|
@@ -28,11 +36,20 @@ export const makeBoundedTTLCache = ({ ttlSeconds = 3600, maxEntries = 1000 } = {
|
|
|
28
36
|
},
|
|
29
37
|
set(key, value) {
|
|
30
38
|
map.set(key, { value, expiresAt: Date.now() + ttlMs });
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
// AunuBaileys (1.0.80, HB-226): the old guard broke out
|
|
40
|
+
// when the oldest KEY was `undefined` — but a Map can
|
|
41
|
+
// legitimately HOLD undefined as a key (two in-tree
|
|
42
|
+
// callers can produce one: a call offer without a
|
|
43
|
+
// call-id, a placeholder resend without a message id),
|
|
44
|
+
// and one such entry silently disabled the ceiling
|
|
45
|
+
// until it expired. The iterator's `done` flag is the
|
|
46
|
+
// real "map is empty" signal; deleting an undefined
|
|
47
|
+
// key is perfectly safe.
|
|
48
|
+
while (map.size > limit) {
|
|
49
|
+
const oldest = map.keys().next();
|
|
50
|
+
if (oldest.done)
|
|
34
51
|
break;
|
|
35
|
-
map.delete(oldest);
|
|
52
|
+
map.delete(oldest.value);
|
|
36
53
|
}
|
|
37
54
|
},
|
|
38
55
|
del(key) {
|
package/lib/Utils/lid-store.js
CHANGED
|
@@ -15,7 +15,16 @@ import { jidNormalizedUser, isJidUser, isLidUser } from '../WABinary/jid-utils.j
|
|
|
15
15
|
* fed manually via `learnFromMessage` / `addPair`.
|
|
16
16
|
*/
|
|
17
17
|
export const makeLIDStore = (options = {}) => {
|
|
18
|
-
|
|
18
|
+
// AunuBaileys (1.0.80, HB-190 + addendum HB-145): `?? 5000`
|
|
19
|
+
// let NaN through (the eviction comparison `size > NaN` is
|
|
20
|
+
// always false — the store grew without bound) and let
|
|
21
|
+
// negatives through (evictIfNeeded's while loop then spun
|
|
22
|
+
// forever on an empty map: `size > -1` stays true while
|
|
23
|
+
// delete(undefined) is a no-op — a wedged process, no error).
|
|
24
|
+
// Sanitise at the boundary: finite values are floored and
|
|
25
|
+
// clamped at 0 (0 = store nothing, which terminates),
|
|
26
|
+
// non-finite values fall back to the default 5000.
|
|
27
|
+
const maxEntries = Number.isFinite(options.maxEntries) ? Math.max(0, Math.floor(options.maxEntries)) : 5000;
|
|
19
28
|
// AunuBaileys (1.0.71): optional listener fired when a genuinely
|
|
20
29
|
// NEW or changed PN<->LID pair is learned (re-learning an already
|
|
21
30
|
// known pair does not fire). The socket wires it to 'lid-mapping.update'.
|
|
@@ -29,7 +38,17 @@ export const makeLIDStore = (options = {}) => {
|
|
|
29
38
|
};
|
|
30
39
|
const evictIfNeeded = () => {
|
|
31
40
|
while (pnToLid.size > maxEntries) {
|
|
32
|
-
|
|
41
|
+
// AunuBaileys (1.0.80, HB-190 defence in depth): with a
|
|
42
|
+
// sanitised maxEntries (>= 0) this loop always
|
|
43
|
+
// terminates, but never trust a loop whose only exit is
|
|
44
|
+
// a size comparison — bail out if the map is somehow
|
|
45
|
+
// already empty (the iterator's `done`, not the key's
|
|
46
|
+
// value, is the empty signal).
|
|
47
|
+
const oldest = pnToLid.keys().next();
|
|
48
|
+
if (oldest.done) {
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
const oldestPn = oldest.value;
|
|
33
52
|
const lid = pnToLid.get(oldestPn);
|
|
34
53
|
pnToLid.delete(oldestPn);
|
|
35
54
|
if (lid) {
|
|
@@ -15,6 +15,14 @@
|
|
|
15
15
|
* `sentMessagesCacheSize: 0` in the socket config to disable.
|
|
16
16
|
*/
|
|
17
17
|
export const makeSentMessageCache = (maxEntries = 256, resolveAlternateJid) => {
|
|
18
|
+
// AunuBaileys (1.0.80, HB-145): a NaN cap (host config from an
|
|
19
|
+
// unset env var — sentMessageCacheFor's typeof check passes NaN
|
|
20
|
+
// straight through) made `cache.size > NaN` false forever, so
|
|
21
|
+
// the cache grew without bound; Infinity did the same.
|
|
22
|
+
// Sanitise at the boundary: finite values are floored and
|
|
23
|
+
// clamped at 0 (0 keeps its documented meaning — the cache is
|
|
24
|
+
// disabled), non-finite values fall back to the default 256.
|
|
25
|
+
const limit = Number.isFinite(maxEntries) ? Math.max(0, Math.floor(maxEntries)) : 256;
|
|
18
26
|
const cache = new Map();
|
|
19
27
|
const keyOf = (remoteJid, id) => `${remoteJid}:${id}`;
|
|
20
28
|
let altResolver = typeof resolveAlternateJid === 'function' ? resolveAlternateJid : undefined;
|
|
@@ -30,13 +38,13 @@ export const makeSentMessageCache = (maxEntries = 256, resolveAlternateJid) => {
|
|
|
30
38
|
}
|
|
31
39
|
},
|
|
32
40
|
add: (remoteJid, id, message) => {
|
|
33
|
-
if (!remoteJid || !id || !message ||
|
|
41
|
+
if (!remoteJid || !id || !message || limit <= 0) {
|
|
34
42
|
return;
|
|
35
43
|
}
|
|
36
44
|
const key = keyOf(remoteJid, id);
|
|
37
45
|
cache.delete(key);
|
|
38
46
|
cache.set(key, message);
|
|
39
|
-
while (cache.size >
|
|
47
|
+
while (cache.size > limit) {
|
|
40
48
|
cache.delete(cache.keys().next().value);
|
|
41
49
|
}
|
|
42
50
|
},
|
package/lib/Utils/signal.js
CHANGED
|
@@ -35,6 +35,19 @@ export const generateOrGetPreKeys = (creds, range) => {
|
|
|
35
35
|
throw new Error('AunuBaileys: creds.nextPreKeyId / creds.firstUnuploadedPreKeyId are missing — the auth state is incomplete or corrupt; restore a full backup or pair again');
|
|
36
36
|
}
|
|
37
37
|
const avaliable = creds.nextPreKeyId - creds.firstUnuploadedPreKeyId;
|
|
38
|
+
// AunuBaileys (1.0.80, HB-140 + HB-225): finite-but-INVERTED
|
|
39
|
+
// counters (firstUnuploadedPreKeyId > nextPreKeyId — hand-edited
|
|
40
|
+
// or partially restored creds) made `remaining` exceed `range`
|
|
41
|
+
// by the size of the gap, so the loop below generated keys for
|
|
42
|
+
// the GAP, not the request: gap 50k ≈ 5 s and +48 MB, gap 200k
|
|
43
|
+
// ≈ 21 s and +238 MB, and a ~2^31 gap would freeze the process
|
|
44
|
+
// outright — synchronously, inside the keys transaction, at
|
|
45
|
+
// every login. Same class as HB-84 above (corrupt counters),
|
|
46
|
+
// same answer: refuse descriptively. With consistent counters
|
|
47
|
+
// `remaining` can never exceed `range` by construction.
|
|
48
|
+
if (avaliable < 0) {
|
|
49
|
+
throw new Error('AunuBaileys: creds pre-key counters are inverted (firstUnuploadedPreKeyId > nextPreKeyId) — the auth state is corrupt; restore a full backup or pair again');
|
|
50
|
+
}
|
|
38
51
|
const remaining = range - avaliable;
|
|
39
52
|
const lastPreKeyId = creds.nextPreKeyId + remaining - 1;
|
|
40
53
|
const newPreKeys = {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aunucore/baileys",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.80",
|
|
5
5
|
"description": "AunuBaileys — the self-healing WhatsApp Web API for Node.js. Bad MAC and \"2000 messages into the future\" errors repair themselves, LID and phone-number identities stay in sync, anti-ban is built in, pairing codes are custom — plus 29 experimental features no other Baileys fork ships: invisible watermarks, per-person tag-all cards, side-profile text, ghost mentions and more. ESM, CJS and full TypeScript types.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"whatsapp",
|