baileys-antiban 3.2.0 → 3.3.0
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/CHANGELOG.md +19 -0
- package/README.md +2 -0
- package/dist/jidCanonicalizer.d.ts +19 -0
- package/dist/jidCanonicalizer.js +70 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.3.0] — 2026-04-26
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`JidCanonicalizer.canonicalKey(jid)`** — Returns stable thread key for DB storage/indexing
|
|
12
|
+
- Solves the split-thread bug from Baileys v7 LID migration ([#1832](https://github.com/WhiskeySockets/Baileys/issues/1832))
|
|
13
|
+
- Always returns same key regardless of whether message arrives as `@lid` or `@s.whatsapp.net`
|
|
14
|
+
- Format: `thread:<digits>` for known contacts, `thread:lid:<digits>` for unknown, `thread:group:<id>` for groups
|
|
15
|
+
- Uses learned LID↔PN mappings when available, falls back to LID form when not
|
|
16
|
+
- Handles edge cases: groups, broadcasts, newsletters, empty/null inputs
|
|
17
|
+
- Tracks stats: `canonicalKeyHits` (PN known) vs `canonicalKeyMisses` (LID only)
|
|
18
|
+
- **`docs/lid-migration.md`** — Comprehensive guide for surviving Baileys v7's LID migration
|
|
19
|
+
- Explains the three major bugs LID causes (#1832 split-thread, #1718 phone lookup, #2030 call routing)
|
|
20
|
+
- Full integration examples: learning from events, canonicalizing sends, stable DB keys
|
|
21
|
+
- Production setup with persistence, stats logging, cleanup
|
|
22
|
+
- Limitations and best practices
|
|
23
|
+
|
|
24
|
+
### Why v3.3
|
|
25
|
+
Baileys v7 made `@lid` the default JID format, but many apps still use `remoteJid` as their database thread key. This causes the same conversation to appear as two separate threads when messages arrive under different forms. `canonicalKey()` provides a stable, form-independent identifier that prevents this split-thread bug. The LID migration doc owns the narrative for the v7 transition.
|
|
26
|
+
|
|
8
27
|
## [3.2.0] — 2026-04-26
|
|
9
28
|
|
|
10
29
|
### New Features
|
package/README.md
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
> Rate limiting with Gaussian jitter, 7-day warmup, session health monitoring, LID resolver, disconnect classification, contact graph enforcement — all in one `npm install`. Works with [Baileys](https://github.com/WhiskeySockets/Baileys) and [@oxidezap/baileyrs](https://github.com/oxidezap/baileyrs) (Rust/WASM).
|
|
11
11
|
|
|
12
|
+
> **New in v3.3:** [LID Migration Guide](./docs/lid-migration.md) — survive Baileys v7's @lid default with stable thread keys.
|
|
13
|
+
|
|
12
14
|
## v2.0 New Features — Session Stability Module
|
|
13
15
|
|
|
14
16
|
### What's New in v2.0
|
|
@@ -39,6 +39,8 @@ export interface JidCanonicalizerStats {
|
|
|
39
39
|
outboundCanonicalized: number;
|
|
40
40
|
outboundPassthrough: number;
|
|
41
41
|
inboundLearned: number;
|
|
42
|
+
canonicalKeyHits: number;
|
|
43
|
+
canonicalKeyMisses: number;
|
|
42
44
|
}
|
|
43
45
|
export declare class JidCanonicalizer {
|
|
44
46
|
private config;
|
|
@@ -54,6 +56,23 @@ export declare class JidCanonicalizer {
|
|
|
54
56
|
* Called by wrapper on every outbound send. Returns canonical JID.
|
|
55
57
|
*/
|
|
56
58
|
canonicalizeTarget(jid: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Returns a stable, canonical thread key for storage / DB indexing.
|
|
61
|
+
*
|
|
62
|
+
* Different from `canonicalizeTarget()` (which picks the right send target):
|
|
63
|
+
* - canonicalizeTarget('1234@lid') → '+27...@s.whatsapp.net' (best send target)
|
|
64
|
+
* - canonicalKey('1234@lid') → 'thread:27...' (stable thread identifier)
|
|
65
|
+
*
|
|
66
|
+
* If LID has known PN mapping → use phone-number form
|
|
67
|
+
* If only LID known → use LID stripped of suffix
|
|
68
|
+
* Always lowercase, no @-suffix, prefixed with `thread:`
|
|
69
|
+
*
|
|
70
|
+
* Apps using this as their DB key won't double-thread on LID/PN drift.
|
|
71
|
+
*
|
|
72
|
+
* @param jid - WhatsApp JID (can be PN, LID, group, or broadcast)
|
|
73
|
+
* @returns Stable thread key for DB indexing
|
|
74
|
+
*/
|
|
75
|
+
canonicalKey(jid: string): string;
|
|
57
76
|
/**
|
|
58
77
|
* Called by wrapper on messages.upsert event. Learns mappings.
|
|
59
78
|
*/
|
package/dist/jidCanonicalizer.js
CHANGED
|
@@ -35,6 +35,8 @@ export class JidCanonicalizer {
|
|
|
35
35
|
outboundCanonicalized: 0,
|
|
36
36
|
outboundPassthrough: 0,
|
|
37
37
|
inboundLearned: 0,
|
|
38
|
+
canonicalKeyHits: 0,
|
|
39
|
+
canonicalKeyMisses: 0,
|
|
38
40
|
};
|
|
39
41
|
constructor(config = {}) {
|
|
40
42
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
@@ -70,6 +72,72 @@ export class JidCanonicalizer {
|
|
|
70
72
|
}
|
|
71
73
|
return canonical;
|
|
72
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Returns a stable, canonical thread key for storage / DB indexing.
|
|
77
|
+
*
|
|
78
|
+
* Different from `canonicalizeTarget()` (which picks the right send target):
|
|
79
|
+
* - canonicalizeTarget('1234@lid') → '+27...@s.whatsapp.net' (best send target)
|
|
80
|
+
* - canonicalKey('1234@lid') → 'thread:27...' (stable thread identifier)
|
|
81
|
+
*
|
|
82
|
+
* If LID has known PN mapping → use phone-number form
|
|
83
|
+
* If only LID known → use LID stripped of suffix
|
|
84
|
+
* Always lowercase, no @-suffix, prefixed with `thread:`
|
|
85
|
+
*
|
|
86
|
+
* Apps using this as their DB key won't double-thread on LID/PN drift.
|
|
87
|
+
*
|
|
88
|
+
* @param jid - WhatsApp JID (can be PN, LID, group, or broadcast)
|
|
89
|
+
* @returns Stable thread key for DB indexing
|
|
90
|
+
*/
|
|
91
|
+
canonicalKey(jid) {
|
|
92
|
+
// Defensive: handle null/undefined/empty
|
|
93
|
+
if (!jid || typeof jid !== 'string' || jid.trim() === '') {
|
|
94
|
+
return 'thread:invalid';
|
|
95
|
+
}
|
|
96
|
+
const normalized = jid.trim().toLowerCase();
|
|
97
|
+
// Extract parts: user@domain
|
|
98
|
+
const atIndex = normalized.indexOf('@');
|
|
99
|
+
if (atIndex === -1) {
|
|
100
|
+
return 'thread:invalid';
|
|
101
|
+
}
|
|
102
|
+
const user = normalized.substring(0, atIndex);
|
|
103
|
+
const domain = normalized.substring(atIndex + 1);
|
|
104
|
+
// Handle special domains
|
|
105
|
+
if (domain === 'g.us') {
|
|
106
|
+
// Group chat
|
|
107
|
+
return `thread:group:${user}`;
|
|
108
|
+
}
|
|
109
|
+
if (domain === 'broadcast') {
|
|
110
|
+
// Broadcast list
|
|
111
|
+
return `thread:broadcast:${user}`;
|
|
112
|
+
}
|
|
113
|
+
if (domain === 'newsletter') {
|
|
114
|
+
// Newsletter (WA Channels)
|
|
115
|
+
return `thread:newsletter:${user}`;
|
|
116
|
+
}
|
|
117
|
+
// Handle @s.whatsapp.net (PN form)
|
|
118
|
+
if (domain === 's.whatsapp.net') {
|
|
119
|
+
this.stats.canonicalKeyHits++;
|
|
120
|
+
return `thread:${user}`;
|
|
121
|
+
}
|
|
122
|
+
// Handle @lid form
|
|
123
|
+
if (domain === 'lid') {
|
|
124
|
+
// Try to resolve to PN via learned mappings
|
|
125
|
+
const mapping = this.lidResolver.getMapping(normalized);
|
|
126
|
+
if (mapping?.pn) {
|
|
127
|
+
// We have a PN mapping — use it
|
|
128
|
+
const pnUser = mapping.pn.split('@')[0];
|
|
129
|
+
this.stats.canonicalKeyHits++;
|
|
130
|
+
return `thread:${pnUser}`;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// No PN known yet — use LID form
|
|
134
|
+
this.stats.canonicalKeyMisses++;
|
|
135
|
+
return `thread:lid:${user}`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Unknown domain — return generic form
|
|
139
|
+
return `thread:${domain}:${user}`;
|
|
140
|
+
}
|
|
73
141
|
/**
|
|
74
142
|
* Called by wrapper on messages.upsert event. Learns mappings.
|
|
75
143
|
*/
|
|
@@ -102,6 +170,8 @@ export class JidCanonicalizer {
|
|
|
102
170
|
outboundCanonicalized: this.stats.outboundCanonicalized,
|
|
103
171
|
outboundPassthrough: this.stats.outboundPassthrough,
|
|
104
172
|
inboundLearned: this.stats.inboundLearned,
|
|
173
|
+
canonicalKeyHits: this.stats.canonicalKeyHits,
|
|
174
|
+
canonicalKeyMisses: this.stats.canonicalKeyMisses,
|
|
105
175
|
};
|
|
106
176
|
}
|
|
107
177
|
destroy() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "baileys-antiban",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Anti-ban middleware for Baileys WhatsApp bots. Rate limiting, warmup, health monitor, LID resolver, disconnect classifier. Free Whapi.Cloud alternative.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|