baileys-antiban 4.7.0 โ 4.9.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/dist/antiban.d.ts +37 -0
- package/dist/antiban.js +134 -0
- package/dist/cjs/antiban.js +134 -0
- package/dist/cjs/index.js +9 -1
- package/dist/cjs/messageTypeRegistry.js +373 -0
- package/dist/cjs/stateExport.js +161 -0
- package/dist/cjs/topologyThrottler.js +343 -0
- package/dist/cjs/warmup.js +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/messageTypeRegistry.d.ts +145 -0
- package/dist/messageTypeRegistry.js +369 -0
- package/dist/stateExport.d.ts +154 -0
- package/dist/stateExport.js +157 -0
- package/dist/topologyThrottler.d.ts +130 -0
- package/dist/topologyThrottler.js +339 -0
- package/dist/warmup.d.ts +4 -0
- package/dist/warmup.js +6 -0
- package/package.json +1 -1
package/dist/antiban.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { ReplyRatioGuard, type ReplyRatioConfig, type ReplyRatioStats } from './
|
|
|
21
21
|
import { ContactGraphWarmer, type ContactGraphConfig, type ContactGraphStats } from './contactGraph.js';
|
|
22
22
|
import { PresenceChoreographer, type PresenceChoreographerConfig, type PresenceChoreographerStats } from './presenceChoreographer.js';
|
|
23
23
|
import { RetryReasonTracker, type RetryTrackerConfig, type RetryStats } from './retryTracker.js';
|
|
24
|
+
import { TopologyThrottler, type TopologyThrottlerConfig } from './topologyThrottler.js';
|
|
24
25
|
import { PostReconnectThrottle, type ReconnectThrottleConfig, type ReconnectThrottleStats } from './reconnectThrottle.js';
|
|
25
26
|
import { LidResolver, type LidResolverConfig, type LidResolverStats } from './lidResolver.js';
|
|
26
27
|
import { JidCanonicalizer, type JidCanonicalizerConfig, type JidCanonicalizerStats } from './jidCanonicalizer.js';
|
|
@@ -29,6 +30,8 @@ import { BanRecoveryOrchestrator, type RecoveryStatus } from './banRecoveryOrche
|
|
|
29
30
|
import { type AntiBanInput, type ResolvedConfig } from './presets.js';
|
|
30
31
|
import { type DeliveryTrackerStats } from './deliveryTracker.js';
|
|
31
32
|
import { type InstanceCoordinatorStats } from './instanceCoordinator.js';
|
|
33
|
+
import { MessageTypeRegistry } from './messageTypeRegistry.js';
|
|
34
|
+
import { type AntibanSnapshot } from './stateExport.js';
|
|
32
35
|
export interface AntiBanConfigLegacy {
|
|
33
36
|
rateLimiter?: Partial<RateLimiterConfig>;
|
|
34
37
|
warmUp?: Partial<WarmUpConfig>;
|
|
@@ -39,6 +42,7 @@ export interface AntiBanConfigLegacy {
|
|
|
39
42
|
presence?: Partial<PresenceChoreographerConfig>;
|
|
40
43
|
retryTracker?: Partial<RetryTrackerConfig>;
|
|
41
44
|
reconnectThrottle?: Partial<ReconnectThrottleConfig>;
|
|
45
|
+
topologyThrottler?: Partial<TopologyThrottlerConfig>;
|
|
42
46
|
lidResolver?: LidResolverConfig;
|
|
43
47
|
jidCanonicalizer?: JidCanonicalizerConfig;
|
|
44
48
|
sessionStability?: {
|
|
@@ -70,12 +74,26 @@ export interface AntiBanStats {
|
|
|
70
74
|
presence?: PresenceChoreographerStats;
|
|
71
75
|
retryTracker?: RetryStats | null;
|
|
72
76
|
reconnectThrottle?: ReconnectThrottleStats | null;
|
|
77
|
+
topologyThrottler?: {
|
|
78
|
+
newContactsThisHour: number;
|
|
79
|
+
newContactsToday: number;
|
|
80
|
+
replyRatio: number | null;
|
|
81
|
+
blockedRatio: number | null;
|
|
82
|
+
hotspots: Array<{
|
|
83
|
+
sourceGroup: string;
|
|
84
|
+
count: number;
|
|
85
|
+
}>;
|
|
86
|
+
} | null;
|
|
73
87
|
lidResolver?: LidResolverStats | null;
|
|
74
88
|
jidCanonicalizer?: JidCanonicalizerStats | null;
|
|
75
89
|
sessionStability?: SessionHealthStats | null;
|
|
76
90
|
banRecovery?: RecoveryStatus | null;
|
|
77
91
|
deliveryTracker: DeliveryTrackerStats;
|
|
78
92
|
instanceCoordinator?: InstanceCoordinatorStats | null;
|
|
93
|
+
messageRegistry?: {
|
|
94
|
+
typeCount: number;
|
|
95
|
+
warningCount: number;
|
|
96
|
+
} | null;
|
|
79
97
|
}
|
|
80
98
|
export declare class AntiBan {
|
|
81
99
|
private rateLimiter;
|
|
@@ -87,12 +105,14 @@ export declare class AntiBan {
|
|
|
87
105
|
private presenceChoreographer;
|
|
88
106
|
private retryTrackerModule;
|
|
89
107
|
private reconnectThrottleModule;
|
|
108
|
+
private topologyThrottlerModule;
|
|
90
109
|
private lidResolverModule;
|
|
91
110
|
private jidCanonicalizerModule;
|
|
92
111
|
private sessionStabilityMonitor;
|
|
93
112
|
private banRecovery;
|
|
94
113
|
private deliveryTracker;
|
|
95
114
|
private instanceCoordinator;
|
|
115
|
+
private messageTypeRegistry;
|
|
96
116
|
private stateManager;
|
|
97
117
|
private resolvedConfig;
|
|
98
118
|
private logging;
|
|
@@ -153,6 +173,10 @@ export declare class AntiBan {
|
|
|
153
173
|
get retryTracker(): RetryReasonTracker;
|
|
154
174
|
/** Get the reconnect throttle for direct access */
|
|
155
175
|
get reconnectThrottle(): PostReconnectThrottle;
|
|
176
|
+
/** Get the topology throttler for direct access */
|
|
177
|
+
get topologyThrottler(): TopologyThrottler | null;
|
|
178
|
+
/** Get the topology throttler for direct access (alias) */
|
|
179
|
+
get topology(): TopologyThrottler | null;
|
|
156
180
|
/** Get the LID resolver for direct access */
|
|
157
181
|
get lidResolver(): LidResolver | null;
|
|
158
182
|
/** Get the JID canonicalizer for direct access */
|
|
@@ -161,6 +185,8 @@ export declare class AntiBan {
|
|
|
161
185
|
get sessionStability(): SessionHealthMonitor | null;
|
|
162
186
|
/** Get the ban recovery orchestrator for direct access */
|
|
163
187
|
get recoveryOrchestrator(): BanRecoveryOrchestrator;
|
|
188
|
+
/** Get the message type registry for direct access */
|
|
189
|
+
get messageRegistry(): MessageTypeRegistry | null;
|
|
164
190
|
/**
|
|
165
191
|
* Export warm-up state for persistence between restarts
|
|
166
192
|
*/
|
|
@@ -177,9 +203,20 @@ export declare class AntiBan {
|
|
|
177
203
|
* Reset everything (use after a ban period)
|
|
178
204
|
*/
|
|
179
205
|
reset(): void;
|
|
206
|
+
private isGroupJid;
|
|
180
207
|
private runAdaptiveCheck;
|
|
181
208
|
private persistStateDebounced;
|
|
182
209
|
private persistStateImmediate;
|
|
210
|
+
/**
|
|
211
|
+
* Export unified state snapshot for Redis failover or cross-instance migration.
|
|
212
|
+
* Returns snapshot of all module states (warmup, health, rate limiter, circuits, etc.)
|
|
213
|
+
*/
|
|
214
|
+
exportState(): AntibanSnapshot;
|
|
215
|
+
/**
|
|
216
|
+
* Import unified state snapshot.
|
|
217
|
+
* CRDT-safe for rate limiters (never overwrites higher counts).
|
|
218
|
+
*/
|
|
219
|
+
importState(snapshot: AntibanSnapshot): void;
|
|
183
220
|
/**
|
|
184
221
|
* Clean up all timers and resources.
|
|
185
222
|
* Call this when disposing of the AntiBan instance or when the socket closes.
|
package/dist/antiban.js
CHANGED
|
@@ -21,6 +21,7 @@ import { ReplyRatioGuard } from './replyRatio.js';
|
|
|
21
21
|
import { ContactGraphWarmer } from './contactGraph.js';
|
|
22
22
|
import { PresenceChoreographer } from './presenceChoreographer.js';
|
|
23
23
|
import { RetryReasonTracker } from './retryTracker.js';
|
|
24
|
+
import { TopologyThrottler } from './topologyThrottler.js';
|
|
24
25
|
import { PostReconnectThrottle } from './reconnectThrottle.js';
|
|
25
26
|
import { LidResolver } from './lidResolver.js';
|
|
26
27
|
import { JidCanonicalizer } from './jidCanonicalizer.js';
|
|
@@ -31,6 +32,8 @@ import { StateManager } from './persist.js';
|
|
|
31
32
|
import { shouldUseGroupProfile, applyGroupMultiplier } from './profiles.js';
|
|
32
33
|
import { DeliveryTracker } from './deliveryTracker.js';
|
|
33
34
|
import { InstanceCoordinator } from './instanceCoordinator.js';
|
|
35
|
+
import { MessageTypeRegistry } from './messageTypeRegistry.js';
|
|
36
|
+
import { exportAntibanState, importAntibanState } from './stateExport.js';
|
|
34
37
|
function isLegacyConfig(cfg) {
|
|
35
38
|
if (typeof cfg !== 'object' || cfg === null)
|
|
36
39
|
return false;
|
|
@@ -103,12 +106,14 @@ export class AntiBan {
|
|
|
103
106
|
presenceChoreographer;
|
|
104
107
|
retryTrackerModule;
|
|
105
108
|
reconnectThrottleModule;
|
|
109
|
+
topologyThrottlerModule = null;
|
|
106
110
|
lidResolverModule = null;
|
|
107
111
|
jidCanonicalizerModule = null;
|
|
108
112
|
sessionStabilityMonitor = null;
|
|
109
113
|
banRecovery;
|
|
110
114
|
deliveryTracker;
|
|
111
115
|
instanceCoordinator = null;
|
|
116
|
+
messageTypeRegistry = null;
|
|
112
117
|
stateManager = null;
|
|
113
118
|
resolvedConfig;
|
|
114
119
|
logging;
|
|
@@ -243,6 +248,13 @@ export class AntiBan {
|
|
|
243
248
|
...(legacyPassthrough?.reconnectThrottle || {}),
|
|
244
249
|
baselineRatePerMinute: () => this.rateLimiter.getStats().limits.perMinute,
|
|
245
250
|
});
|
|
251
|
+
// Initialize topology throttler if configured
|
|
252
|
+
if (legacyPassthrough?.topologyThrottler) {
|
|
253
|
+
this.topologyThrottlerModule = new TopologyThrottler(legacyPassthrough.topologyThrottler);
|
|
254
|
+
if (this.logging) {
|
|
255
|
+
console.log(`[baileys-antiban] ๐ Topology throttler enabled โ max ${legacyPassthrough.topologyThrottler.maxNewContactsPerHour || 5}/hr, ${legacyPassthrough.topologyThrottler.maxNewContactsPerDay || 20}/day new contacts`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
246
258
|
// Initialize LID resolver and canonicalizer if configured
|
|
247
259
|
// If jidCanonicalizer is enabled but no resolver provided, create standalone resolver
|
|
248
260
|
if (legacyPassthrough?.jidCanonicalizer?.enabled) {
|
|
@@ -297,6 +309,13 @@ export class AntiBan {
|
|
|
297
309
|
console.log(`[baileys-antiban] ๐ Instance coordination enabled: ${cfg.instanceCoordinator}`);
|
|
298
310
|
}
|
|
299
311
|
}
|
|
312
|
+
// Initialize message type registry if configured
|
|
313
|
+
if (cfg.messageTypeRegistry) {
|
|
314
|
+
this.messageTypeRegistry = new MessageTypeRegistry();
|
|
315
|
+
if (this.logging) {
|
|
316
|
+
console.log(`[baileys-antiban] ๐ Message type registry enabled`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
300
319
|
}
|
|
301
320
|
/**
|
|
302
321
|
* Check if a message can be sent and get required delay.
|
|
@@ -371,6 +390,46 @@ export class AntiBan {
|
|
|
371
390
|
health: healthStatus,
|
|
372
391
|
};
|
|
373
392
|
}
|
|
393
|
+
// Topology throttler check โ only applies to DMs to new/unknown contacts
|
|
394
|
+
if (this.topologyThrottlerModule && !this.isGroupJid(recipient)) {
|
|
395
|
+
const knownChats = this.rateLimiter.getKnownChats();
|
|
396
|
+
const isNewContact = !knownChats.has(recipient);
|
|
397
|
+
if (isNewContact) {
|
|
398
|
+
// Check if we can send to new contact based on topology limits
|
|
399
|
+
const topologyDecision = this.topologyThrottlerModule.canSendToNewContact();
|
|
400
|
+
if (!topologyDecision.allowed) {
|
|
401
|
+
this.stats.messagesBlocked++;
|
|
402
|
+
if (this.logging) {
|
|
403
|
+
console.log(`[baileys-antiban] ๐ BLOCKED โ topology: ${topologyDecision.reason}`);
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
allowed: false,
|
|
407
|
+
delayMs: topologyDecision.retryAfterMs || 0,
|
|
408
|
+
reason: `Topology: ${topologyDecision.reason}`,
|
|
409
|
+
health: healthStatus,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
// Assess contact risk
|
|
413
|
+
const riskAssessment = this.topologyThrottlerModule.assessContact(recipient, {
|
|
414
|
+
messageType: 'dm',
|
|
415
|
+
hasReplied: false,
|
|
416
|
+
knownGroups: [],
|
|
417
|
+
});
|
|
418
|
+
if (riskAssessment.recommendation === 'abort') {
|
|
419
|
+
this.stats.messagesBlocked++;
|
|
420
|
+
if (this.logging) {
|
|
421
|
+
console.log(`[baileys-antiban] โ BLOCKED โ contact risk ${riskAssessment.risk} (score ${riskAssessment.score}): ${riskAssessment.reasons.join(', ')}`);
|
|
422
|
+
}
|
|
423
|
+
return {
|
|
424
|
+
allowed: false,
|
|
425
|
+
delayMs: 0,
|
|
426
|
+
reason: `Contact risk too high: ${riskAssessment.reasons.join(', ')}`,
|
|
427
|
+
health: healthStatus,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
// If delay recommended, we'll add it to the total delay later
|
|
431
|
+
}
|
|
432
|
+
}
|
|
374
433
|
// Reply ratio check
|
|
375
434
|
const replyRatioDecision = this.replyRatioGuard.beforeSend(recipient);
|
|
376
435
|
if (!replyRatioDecision.allowed) {
|
|
@@ -472,6 +531,24 @@ export class AntiBan {
|
|
|
472
531
|
}
|
|
473
532
|
}
|
|
474
533
|
}
|
|
534
|
+
// Topology throttler recommended delay
|
|
535
|
+
if (this.topologyThrottlerModule && !this.isGroupJid(recipient)) {
|
|
536
|
+
const knownChats = this.rateLimiter.getKnownChats();
|
|
537
|
+
const isNewContact = !knownChats.has(recipient);
|
|
538
|
+
if (isNewContact) {
|
|
539
|
+
const riskAssessment = this.topologyThrottlerModule.assessContact(recipient, {
|
|
540
|
+
messageType: 'dm',
|
|
541
|
+
hasReplied: false,
|
|
542
|
+
knownGroups: [],
|
|
543
|
+
});
|
|
544
|
+
if (riskAssessment.recommendation === 'delay' && riskAssessment.suggestedDelayMs) {
|
|
545
|
+
delay += riskAssessment.suggestedDelayMs;
|
|
546
|
+
if (this.logging) {
|
|
547
|
+
console.log(`[baileys-antiban] โ ๏ธ Topology risk ${riskAssessment.risk} โ adding ${Math.floor(riskAssessment.suggestedDelayMs / 60000)}min delay`);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
475
552
|
// Roll for distraction pause
|
|
476
553
|
const distractionCheck = this.presenceChoreographer.shouldPauseForDistraction();
|
|
477
554
|
if (distractionCheck.pause) {
|
|
@@ -503,6 +580,7 @@ export class AntiBan {
|
|
|
503
580
|
this.rateLimiter.record(recipient, content);
|
|
504
581
|
this.warmUp.record();
|
|
505
582
|
this.replyRatioGuard.recordSent(recipient);
|
|
583
|
+
this.topologyThrottlerModule?.recordSent(recipient);
|
|
506
584
|
this.stats.messagesAllowed++;
|
|
507
585
|
if (msgId) {
|
|
508
586
|
this.deliveryTracker.onMessageSent(msgId);
|
|
@@ -542,6 +620,7 @@ export class AntiBan {
|
|
|
542
620
|
onIncomingMessage(jid, msgText) {
|
|
543
621
|
this.replyRatioGuard.recordReceived(jid);
|
|
544
622
|
this.contactGraphWarmer.onIncomingMessage(jid);
|
|
623
|
+
this.topologyThrottlerModule?.recordReplied(jid);
|
|
545
624
|
return this.replyRatioGuard.suggestReply(jid, msgText);
|
|
546
625
|
}
|
|
547
626
|
/**
|
|
@@ -585,6 +664,9 @@ export class AntiBan {
|
|
|
585
664
|
if (this.reconnectThrottleModule['config']?.enabled) {
|
|
586
665
|
stats.reconnectThrottle = this.reconnectThrottleModule.getStats();
|
|
587
666
|
}
|
|
667
|
+
if (this.topologyThrottlerModule) {
|
|
668
|
+
stats.topologyThrottler = this.topologyThrottlerModule.getTopologyStats();
|
|
669
|
+
}
|
|
588
670
|
if (this.lidResolverModule) {
|
|
589
671
|
stats.lidResolver = this.lidResolverModule.getStats();
|
|
590
672
|
}
|
|
@@ -597,6 +679,13 @@ export class AntiBan {
|
|
|
597
679
|
if (this.instanceCoordinator) {
|
|
598
680
|
stats.instanceCoordinator = this.instanceCoordinator.getStats();
|
|
599
681
|
}
|
|
682
|
+
if (this.messageTypeRegistry) {
|
|
683
|
+
const warnings = this.messageTypeRegistry.getWarnings();
|
|
684
|
+
stats.messageRegistry = {
|
|
685
|
+
typeCount: Array.from(this.messageTypeRegistry.types.keys()).length,
|
|
686
|
+
warningCount: warnings.length,
|
|
687
|
+
};
|
|
688
|
+
}
|
|
600
689
|
return stats;
|
|
601
690
|
}
|
|
602
691
|
/** Get the timelock guard for direct access */
|
|
@@ -623,6 +712,14 @@ export class AntiBan {
|
|
|
623
712
|
get reconnectThrottle() {
|
|
624
713
|
return this.reconnectThrottleModule;
|
|
625
714
|
}
|
|
715
|
+
/** Get the topology throttler for direct access */
|
|
716
|
+
get topologyThrottler() {
|
|
717
|
+
return this.topologyThrottlerModule;
|
|
718
|
+
}
|
|
719
|
+
/** Get the topology throttler for direct access (alias) */
|
|
720
|
+
get topology() {
|
|
721
|
+
return this.topologyThrottlerModule;
|
|
722
|
+
}
|
|
626
723
|
/** Get the LID resolver for direct access */
|
|
627
724
|
get lidResolver() {
|
|
628
725
|
return this.lidResolverModule;
|
|
@@ -639,6 +736,10 @@ export class AntiBan {
|
|
|
639
736
|
get recoveryOrchestrator() {
|
|
640
737
|
return this.banRecovery;
|
|
641
738
|
}
|
|
739
|
+
/** Get the message type registry for direct access */
|
|
740
|
+
get messageRegistry() {
|
|
741
|
+
return this.messageTypeRegistry;
|
|
742
|
+
}
|
|
642
743
|
/**
|
|
643
744
|
* Export warm-up state for persistence between restarts
|
|
644
745
|
*/
|
|
@@ -680,6 +781,9 @@ export class AntiBan {
|
|
|
680
781
|
console.log('[baileys-antiban] ๐ Reset โ starting fresh warm-up');
|
|
681
782
|
}
|
|
682
783
|
}
|
|
784
|
+
isGroupJid(jid) {
|
|
785
|
+
return jid.endsWith('@g.us') || jid.endsWith('@newsletter');
|
|
786
|
+
}
|
|
683
787
|
runAdaptiveCheck() {
|
|
684
788
|
const delivery = this.deliveryTracker.getStats();
|
|
685
789
|
// Need min sample to be meaningful
|
|
@@ -731,6 +835,35 @@ export class AntiBan {
|
|
|
731
835
|
};
|
|
732
836
|
this.stateManager.saveImmediate(state);
|
|
733
837
|
}
|
|
838
|
+
/**
|
|
839
|
+
* Export unified state snapshot for Redis failover or cross-instance migration.
|
|
840
|
+
* Returns snapshot of all module states (warmup, health, rate limiter, circuits, etc.)
|
|
841
|
+
*/
|
|
842
|
+
exportState() {
|
|
843
|
+
return exportAntibanState({
|
|
844
|
+
warmup: this.warmUp,
|
|
845
|
+
health: this.health,
|
|
846
|
+
rateLimiter: this.rateLimiter,
|
|
847
|
+
timelockGuard: this.timelockGuard,
|
|
848
|
+
messageRegistry: this.messageTypeRegistry || undefined,
|
|
849
|
+
topologyThrottler: this.topologyThrottlerModule || undefined,
|
|
850
|
+
instanceId: this.resolvedConfig.instanceId,
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Import unified state snapshot.
|
|
855
|
+
* CRDT-safe for rate limiters (never overwrites higher counts).
|
|
856
|
+
*/
|
|
857
|
+
importState(snapshot) {
|
|
858
|
+
importAntibanState(snapshot, {
|
|
859
|
+
warmup: this.warmUp,
|
|
860
|
+
health: this.health,
|
|
861
|
+
rateLimiter: this.rateLimiter,
|
|
862
|
+
timelockGuard: this.timelockGuard,
|
|
863
|
+
messageRegistry: this.messageTypeRegistry || undefined,
|
|
864
|
+
topologyThrottler: this.topologyThrottlerModule || undefined,
|
|
865
|
+
});
|
|
866
|
+
}
|
|
734
867
|
/**
|
|
735
868
|
* Clean up all timers and resources.
|
|
736
869
|
* Call this when disposing of the AntiBan instance or when the socket closes.
|
|
@@ -746,6 +879,7 @@ export class AntiBan {
|
|
|
746
879
|
this.jidCanonicalizerModule?.destroy();
|
|
747
880
|
this.lidResolverModule?.destroy();
|
|
748
881
|
this.sessionStabilityMonitor?.reset();
|
|
882
|
+
this.messageTypeRegistry?.cleanup();
|
|
749
883
|
if (this.logging) {
|
|
750
884
|
console.log('[baileys-antiban] ๐งน Destroyed โ all timers cleared');
|
|
751
885
|
}
|
package/dist/cjs/antiban.js
CHANGED
|
@@ -24,6 +24,7 @@ const replyRatio_js_1 = require("./replyRatio.js");
|
|
|
24
24
|
const contactGraph_js_1 = require("./contactGraph.js");
|
|
25
25
|
const presenceChoreographer_js_1 = require("./presenceChoreographer.js");
|
|
26
26
|
const retryTracker_js_1 = require("./retryTracker.js");
|
|
27
|
+
const topologyThrottler_js_1 = require("./topologyThrottler.js");
|
|
27
28
|
const reconnectThrottle_js_1 = require("./reconnectThrottle.js");
|
|
28
29
|
const lidResolver_js_1 = require("./lidResolver.js");
|
|
29
30
|
const jidCanonicalizer_js_1 = require("./jidCanonicalizer.js");
|
|
@@ -34,6 +35,8 @@ const persist_js_1 = require("./persist.js");
|
|
|
34
35
|
const profiles_js_1 = require("./profiles.js");
|
|
35
36
|
const deliveryTracker_js_1 = require("./deliveryTracker.js");
|
|
36
37
|
const instanceCoordinator_js_1 = require("./instanceCoordinator.js");
|
|
38
|
+
const messageTypeRegistry_js_1 = require("./messageTypeRegistry.js");
|
|
39
|
+
const stateExport_js_1 = require("./stateExport.js");
|
|
37
40
|
function isLegacyConfig(cfg) {
|
|
38
41
|
if (typeof cfg !== 'object' || cfg === null)
|
|
39
42
|
return false;
|
|
@@ -106,12 +109,14 @@ class AntiBan {
|
|
|
106
109
|
presenceChoreographer;
|
|
107
110
|
retryTrackerModule;
|
|
108
111
|
reconnectThrottleModule;
|
|
112
|
+
topologyThrottlerModule = null;
|
|
109
113
|
lidResolverModule = null;
|
|
110
114
|
jidCanonicalizerModule = null;
|
|
111
115
|
sessionStabilityMonitor = null;
|
|
112
116
|
banRecovery;
|
|
113
117
|
deliveryTracker;
|
|
114
118
|
instanceCoordinator = null;
|
|
119
|
+
messageTypeRegistry = null;
|
|
115
120
|
stateManager = null;
|
|
116
121
|
resolvedConfig;
|
|
117
122
|
logging;
|
|
@@ -246,6 +251,13 @@ class AntiBan {
|
|
|
246
251
|
...(legacyPassthrough?.reconnectThrottle || {}),
|
|
247
252
|
baselineRatePerMinute: () => this.rateLimiter.getStats().limits.perMinute,
|
|
248
253
|
});
|
|
254
|
+
// Initialize topology throttler if configured
|
|
255
|
+
if (legacyPassthrough?.topologyThrottler) {
|
|
256
|
+
this.topologyThrottlerModule = new topologyThrottler_js_1.TopologyThrottler(legacyPassthrough.topologyThrottler);
|
|
257
|
+
if (this.logging) {
|
|
258
|
+
console.log(`[baileys-antiban] ๐ Topology throttler enabled โ max ${legacyPassthrough.topologyThrottler.maxNewContactsPerHour || 5}/hr, ${legacyPassthrough.topologyThrottler.maxNewContactsPerDay || 20}/day new contacts`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
249
261
|
// Initialize LID resolver and canonicalizer if configured
|
|
250
262
|
// If jidCanonicalizer is enabled but no resolver provided, create standalone resolver
|
|
251
263
|
if (legacyPassthrough?.jidCanonicalizer?.enabled) {
|
|
@@ -300,6 +312,13 @@ class AntiBan {
|
|
|
300
312
|
console.log(`[baileys-antiban] ๐ Instance coordination enabled: ${cfg.instanceCoordinator}`);
|
|
301
313
|
}
|
|
302
314
|
}
|
|
315
|
+
// Initialize message type registry if configured
|
|
316
|
+
if (cfg.messageTypeRegistry) {
|
|
317
|
+
this.messageTypeRegistry = new messageTypeRegistry_js_1.MessageTypeRegistry();
|
|
318
|
+
if (this.logging) {
|
|
319
|
+
console.log(`[baileys-antiban] ๐ Message type registry enabled`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
303
322
|
}
|
|
304
323
|
/**
|
|
305
324
|
* Check if a message can be sent and get required delay.
|
|
@@ -374,6 +393,46 @@ class AntiBan {
|
|
|
374
393
|
health: healthStatus,
|
|
375
394
|
};
|
|
376
395
|
}
|
|
396
|
+
// Topology throttler check โ only applies to DMs to new/unknown contacts
|
|
397
|
+
if (this.topologyThrottlerModule && !this.isGroupJid(recipient)) {
|
|
398
|
+
const knownChats = this.rateLimiter.getKnownChats();
|
|
399
|
+
const isNewContact = !knownChats.has(recipient);
|
|
400
|
+
if (isNewContact) {
|
|
401
|
+
// Check if we can send to new contact based on topology limits
|
|
402
|
+
const topologyDecision = this.topologyThrottlerModule.canSendToNewContact();
|
|
403
|
+
if (!topologyDecision.allowed) {
|
|
404
|
+
this.stats.messagesBlocked++;
|
|
405
|
+
if (this.logging) {
|
|
406
|
+
console.log(`[baileys-antiban] ๐ BLOCKED โ topology: ${topologyDecision.reason}`);
|
|
407
|
+
}
|
|
408
|
+
return {
|
|
409
|
+
allowed: false,
|
|
410
|
+
delayMs: topologyDecision.retryAfterMs || 0,
|
|
411
|
+
reason: `Topology: ${topologyDecision.reason}`,
|
|
412
|
+
health: healthStatus,
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
// Assess contact risk
|
|
416
|
+
const riskAssessment = this.topologyThrottlerModule.assessContact(recipient, {
|
|
417
|
+
messageType: 'dm',
|
|
418
|
+
hasReplied: false,
|
|
419
|
+
knownGroups: [],
|
|
420
|
+
});
|
|
421
|
+
if (riskAssessment.recommendation === 'abort') {
|
|
422
|
+
this.stats.messagesBlocked++;
|
|
423
|
+
if (this.logging) {
|
|
424
|
+
console.log(`[baileys-antiban] โ BLOCKED โ contact risk ${riskAssessment.risk} (score ${riskAssessment.score}): ${riskAssessment.reasons.join(', ')}`);
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
allowed: false,
|
|
428
|
+
delayMs: 0,
|
|
429
|
+
reason: `Contact risk too high: ${riskAssessment.reasons.join(', ')}`,
|
|
430
|
+
health: healthStatus,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
// If delay recommended, we'll add it to the total delay later
|
|
434
|
+
}
|
|
435
|
+
}
|
|
377
436
|
// Reply ratio check
|
|
378
437
|
const replyRatioDecision = this.replyRatioGuard.beforeSend(recipient);
|
|
379
438
|
if (!replyRatioDecision.allowed) {
|
|
@@ -475,6 +534,24 @@ class AntiBan {
|
|
|
475
534
|
}
|
|
476
535
|
}
|
|
477
536
|
}
|
|
537
|
+
// Topology throttler recommended delay
|
|
538
|
+
if (this.topologyThrottlerModule && !this.isGroupJid(recipient)) {
|
|
539
|
+
const knownChats = this.rateLimiter.getKnownChats();
|
|
540
|
+
const isNewContact = !knownChats.has(recipient);
|
|
541
|
+
if (isNewContact) {
|
|
542
|
+
const riskAssessment = this.topologyThrottlerModule.assessContact(recipient, {
|
|
543
|
+
messageType: 'dm',
|
|
544
|
+
hasReplied: false,
|
|
545
|
+
knownGroups: [],
|
|
546
|
+
});
|
|
547
|
+
if (riskAssessment.recommendation === 'delay' && riskAssessment.suggestedDelayMs) {
|
|
548
|
+
delay += riskAssessment.suggestedDelayMs;
|
|
549
|
+
if (this.logging) {
|
|
550
|
+
console.log(`[baileys-antiban] โ ๏ธ Topology risk ${riskAssessment.risk} โ adding ${Math.floor(riskAssessment.suggestedDelayMs / 60000)}min delay`);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
478
555
|
// Roll for distraction pause
|
|
479
556
|
const distractionCheck = this.presenceChoreographer.shouldPauseForDistraction();
|
|
480
557
|
if (distractionCheck.pause) {
|
|
@@ -506,6 +583,7 @@ class AntiBan {
|
|
|
506
583
|
this.rateLimiter.record(recipient, content);
|
|
507
584
|
this.warmUp.record();
|
|
508
585
|
this.replyRatioGuard.recordSent(recipient);
|
|
586
|
+
this.topologyThrottlerModule?.recordSent(recipient);
|
|
509
587
|
this.stats.messagesAllowed++;
|
|
510
588
|
if (msgId) {
|
|
511
589
|
this.deliveryTracker.onMessageSent(msgId);
|
|
@@ -545,6 +623,7 @@ class AntiBan {
|
|
|
545
623
|
onIncomingMessage(jid, msgText) {
|
|
546
624
|
this.replyRatioGuard.recordReceived(jid);
|
|
547
625
|
this.contactGraphWarmer.onIncomingMessage(jid);
|
|
626
|
+
this.topologyThrottlerModule?.recordReplied(jid);
|
|
548
627
|
return this.replyRatioGuard.suggestReply(jid, msgText);
|
|
549
628
|
}
|
|
550
629
|
/**
|
|
@@ -588,6 +667,9 @@ class AntiBan {
|
|
|
588
667
|
if (this.reconnectThrottleModule['config']?.enabled) {
|
|
589
668
|
stats.reconnectThrottle = this.reconnectThrottleModule.getStats();
|
|
590
669
|
}
|
|
670
|
+
if (this.topologyThrottlerModule) {
|
|
671
|
+
stats.topologyThrottler = this.topologyThrottlerModule.getTopologyStats();
|
|
672
|
+
}
|
|
591
673
|
if (this.lidResolverModule) {
|
|
592
674
|
stats.lidResolver = this.lidResolverModule.getStats();
|
|
593
675
|
}
|
|
@@ -600,6 +682,13 @@ class AntiBan {
|
|
|
600
682
|
if (this.instanceCoordinator) {
|
|
601
683
|
stats.instanceCoordinator = this.instanceCoordinator.getStats();
|
|
602
684
|
}
|
|
685
|
+
if (this.messageTypeRegistry) {
|
|
686
|
+
const warnings = this.messageTypeRegistry.getWarnings();
|
|
687
|
+
stats.messageRegistry = {
|
|
688
|
+
typeCount: Array.from(this.messageTypeRegistry.types.keys()).length,
|
|
689
|
+
warningCount: warnings.length,
|
|
690
|
+
};
|
|
691
|
+
}
|
|
603
692
|
return stats;
|
|
604
693
|
}
|
|
605
694
|
/** Get the timelock guard for direct access */
|
|
@@ -626,6 +715,14 @@ class AntiBan {
|
|
|
626
715
|
get reconnectThrottle() {
|
|
627
716
|
return this.reconnectThrottleModule;
|
|
628
717
|
}
|
|
718
|
+
/** Get the topology throttler for direct access */
|
|
719
|
+
get topologyThrottler() {
|
|
720
|
+
return this.topologyThrottlerModule;
|
|
721
|
+
}
|
|
722
|
+
/** Get the topology throttler for direct access (alias) */
|
|
723
|
+
get topology() {
|
|
724
|
+
return this.topologyThrottlerModule;
|
|
725
|
+
}
|
|
629
726
|
/** Get the LID resolver for direct access */
|
|
630
727
|
get lidResolver() {
|
|
631
728
|
return this.lidResolverModule;
|
|
@@ -642,6 +739,10 @@ class AntiBan {
|
|
|
642
739
|
get recoveryOrchestrator() {
|
|
643
740
|
return this.banRecovery;
|
|
644
741
|
}
|
|
742
|
+
/** Get the message type registry for direct access */
|
|
743
|
+
get messageRegistry() {
|
|
744
|
+
return this.messageTypeRegistry;
|
|
745
|
+
}
|
|
645
746
|
/**
|
|
646
747
|
* Export warm-up state for persistence between restarts
|
|
647
748
|
*/
|
|
@@ -683,6 +784,9 @@ class AntiBan {
|
|
|
683
784
|
console.log('[baileys-antiban] ๐ Reset โ starting fresh warm-up');
|
|
684
785
|
}
|
|
685
786
|
}
|
|
787
|
+
isGroupJid(jid) {
|
|
788
|
+
return jid.endsWith('@g.us') || jid.endsWith('@newsletter');
|
|
789
|
+
}
|
|
686
790
|
runAdaptiveCheck() {
|
|
687
791
|
const delivery = this.deliveryTracker.getStats();
|
|
688
792
|
// Need min sample to be meaningful
|
|
@@ -734,6 +838,35 @@ class AntiBan {
|
|
|
734
838
|
};
|
|
735
839
|
this.stateManager.saveImmediate(state);
|
|
736
840
|
}
|
|
841
|
+
/**
|
|
842
|
+
* Export unified state snapshot for Redis failover or cross-instance migration.
|
|
843
|
+
* Returns snapshot of all module states (warmup, health, rate limiter, circuits, etc.)
|
|
844
|
+
*/
|
|
845
|
+
exportState() {
|
|
846
|
+
return (0, stateExport_js_1.exportAntibanState)({
|
|
847
|
+
warmup: this.warmUp,
|
|
848
|
+
health: this.health,
|
|
849
|
+
rateLimiter: this.rateLimiter,
|
|
850
|
+
timelockGuard: this.timelockGuard,
|
|
851
|
+
messageRegistry: this.messageTypeRegistry || undefined,
|
|
852
|
+
topologyThrottler: this.topologyThrottlerModule || undefined,
|
|
853
|
+
instanceId: this.resolvedConfig.instanceId,
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Import unified state snapshot.
|
|
858
|
+
* CRDT-safe for rate limiters (never overwrites higher counts).
|
|
859
|
+
*/
|
|
860
|
+
importState(snapshot) {
|
|
861
|
+
(0, stateExport_js_1.importAntibanState)(snapshot, {
|
|
862
|
+
warmup: this.warmUp,
|
|
863
|
+
health: this.health,
|
|
864
|
+
rateLimiter: this.rateLimiter,
|
|
865
|
+
timelockGuard: this.timelockGuard,
|
|
866
|
+
messageRegistry: this.messageTypeRegistry || undefined,
|
|
867
|
+
topologyThrottler: this.topologyThrottlerModule || undefined,
|
|
868
|
+
});
|
|
869
|
+
}
|
|
737
870
|
/**
|
|
738
871
|
* Clean up all timers and resources.
|
|
739
872
|
* Call this when disposing of the AntiBan instance or when the socket closes.
|
|
@@ -749,6 +882,7 @@ class AntiBan {
|
|
|
749
882
|
this.jidCanonicalizerModule?.destroy();
|
|
750
883
|
this.lidResolverModule?.destroy();
|
|
751
884
|
this.sessionStabilityMonitor?.reset();
|
|
885
|
+
this.messageTypeRegistry?.cleanup();
|
|
752
886
|
if (this.logging) {
|
|
753
887
|
console.log('[baileys-antiban] ๐งน Destroyed โ all timers cleared');
|
|
754
888
|
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.getRetryJitter = exports.getTypingJitter = exports.getMessageSendJitter = exports.applySessionFingerprint = exports.generateSessionFingerprint = exports.proxyRotator = exports.readReceiptVariance = exports.credsSnapshot = exports.applyFingerprint = exports.generateFingerprint = exports.messageRecovery = exports.applyGroupMultiplier = exports.shouldUseGroupProfile = exports.isBroadcast = exports.isNewsletter = exports.isGroup = exports.StateManager = exports.PRESETS = exports.resolveConfig = exports.FileStateAdapter = exports.Scheduler = exports.WebhookAlerts = exports.ContentVariator = exports.MessageQueue = exports.wrapSocketWithFingerprint = exports.wrapSocket = exports.getRetryReasonDescription = exports.isMacError = exports.parseRetryReason = exports.MAC_ERROR_CODES = exports.MessageRetryReason = exports.createLidFirstResolver = exports.LidFirstResolver = exports.DeafSessionDetector = exports.classifyDisconnect = exports.wrapWithSessionStability = exports.SessionHealthMonitor = exports.JidCanonicalizer = exports.LidResolver = exports.PostReconnectThrottle = exports.RetryReasonTracker = exports.getCircadianMultiplier = exports.PresenceChoreographer = exports.ContactGraphWarmer = exports.ReplyRatioGuard = exports.TimelockGuard = exports.HealthMonitor = exports.WarmUp = exports.RateLimiter = exports.AntiBan = void 0;
|
|
13
|
-
exports.createPeriodicExporter = exports.createMetricsHandler = exports.exportPrometheusMetrics = exports.createConsoleLogger = exports.createHumanEntropyService = exports.HumanEntropyService = exports.createInMemoryEventStoreBackend = exports.createMySQLEventStoreBackend = exports.createFleetEventStore = exports.createJidCircuitBreaker = exports.JidCircuitBreaker = exports.InstanceCoordinator = exports.DeliveryTracker = exports.BanRecoveryOrchestrator = exports.LegitimacySignalInjector = exports.GROUP_OP_ERRORS = exports.extractPrivacyBlock = exports.classifyGroupOpError = exports.GroupOperationGuard = exports.AbortError = exports.STEALTH_BROWSER_POOL = exports.rampPresenceAfterConnect = exports.getStealthSocketConfig = exports.createStealthFingerprint = exports.getBatteryState = exports.getVoiceNoteMetadata = void 0;
|
|
13
|
+
exports.createPeriodicExporter = exports.createMetricsHandler = exports.exportPrometheusMetrics = exports.createConsoleLogger = exports.TopologyThrottler = exports.importAntibanState = exports.exportAntibanState = exports.MessageTypeRegistry = exports.createHumanEntropyService = exports.HumanEntropyService = exports.createInMemoryEventStoreBackend = exports.createMySQLEventStoreBackend = exports.createFleetEventStore = exports.createJidCircuitBreaker = exports.JidCircuitBreaker = exports.InstanceCoordinator = exports.DeliveryTracker = exports.BanRecoveryOrchestrator = exports.LegitimacySignalInjector = exports.GROUP_OP_ERRORS = exports.extractPrivacyBlock = exports.classifyGroupOpError = exports.GroupOperationGuard = exports.AbortError = exports.STEALTH_BROWSER_POOL = exports.rampPresenceAfterConnect = exports.getStealthSocketConfig = exports.createStealthFingerprint = exports.getBatteryState = exports.getVoiceNoteMetadata = void 0;
|
|
14
14
|
// Core
|
|
15
15
|
var antiban_js_1 = require("./antiban.js");
|
|
16
16
|
Object.defineProperty(exports, "AntiBan", { enumerable: true, get: function () { return antiban_js_1.AntiBan; } });
|
|
@@ -143,6 +143,14 @@ Object.defineProperty(exports, "createInMemoryEventStoreBackend", { enumerable:
|
|
|
143
143
|
var humanEntropy_js_1 = require("./humanEntropy.js");
|
|
144
144
|
Object.defineProperty(exports, "HumanEntropyService", { enumerable: true, get: function () { return humanEntropy_js_1.HumanEntropyService; } });
|
|
145
145
|
Object.defineProperty(exports, "createHumanEntropyService", { enumerable: true, get: function () { return humanEntropy_js_1.createHumanEntropyService; } });
|
|
146
|
+
// v4.8 new modules
|
|
147
|
+
var messageTypeRegistry_js_1 = require("./messageTypeRegistry.js");
|
|
148
|
+
Object.defineProperty(exports, "MessageTypeRegistry", { enumerable: true, get: function () { return messageTypeRegistry_js_1.MessageTypeRegistry; } });
|
|
149
|
+
var stateExport_js_1 = require("./stateExport.js");
|
|
150
|
+
Object.defineProperty(exports, "exportAntibanState", { enumerable: true, get: function () { return stateExport_js_1.exportAntibanState; } });
|
|
151
|
+
Object.defineProperty(exports, "importAntibanState", { enumerable: true, get: function () { return stateExport_js_1.importAntibanState; } });
|
|
152
|
+
var topologyThrottler_js_1 = require("./topologyThrottler.js");
|
|
153
|
+
Object.defineProperty(exports, "TopologyThrottler", { enumerable: true, get: function () { return topologyThrottler_js_1.TopologyThrottler; } });
|
|
146
154
|
// Observability
|
|
147
155
|
var observability_js_1 = require("./observability.js");
|
|
148
156
|
Object.defineProperty(exports, "createConsoleLogger", { enumerable: true, get: function () { return observability_js_1.createConsoleLogger; } });
|