@badzz88/baileys 8.5.2 → 8.5.4

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.
Files changed (110) hide show
  1. package/README.md +1 -1
  2. package/WAProto/WAProto.proto +1256 -75
  3. package/WAProto/index.d.ts +36042 -19649
  4. package/WAProto/index.js +181990 -135645
  5. package/engine-requirements.js +7 -15
  6. package/lib/Defaults/index.js +22 -17
  7. package/lib/Signal/Group/group_cipher.js +5 -5
  8. package/lib/Signal/Group/keyhelper.js +4 -4
  9. package/lib/Signal/Group/sender-chain-key.js +2 -2
  10. package/lib/Signal/Group/sender-key-distribution-message.js +1 -1
  11. package/lib/Signal/Group/sender-key-message.js +3 -3
  12. package/lib/Signal/Group/sender-key-record.js +1 -1
  13. package/lib/Signal/Group/sender-message-key.js +5 -5
  14. package/lib/Signal/libsignal.js +39 -59
  15. package/lib/Signal/lid-mapping.js +28 -10
  16. package/lib/Socket/aigroups.js +5 -5
  17. package/lib/Socket/business.js +3 -11
  18. package/lib/Socket/chats.js +668 -319
  19. package/lib/Socket/communities.js +85 -89
  20. package/lib/Socket/graphql.js +435 -228
  21. package/lib/Socket/groups.js +132 -211
  22. package/lib/Socket/index.js +9 -7
  23. package/lib/Socket/interactive-handler.js +117 -60
  24. package/lib/Socket/interop.js +56 -175
  25. package/lib/Socket/managed-account.js +79 -48
  26. package/lib/Socket/messages-recv.js +898 -340
  27. package/lib/Socket/messages-send.js +462 -160
  28. package/lib/Socket/mex.js +40 -53
  29. package/lib/Socket/newsletter.js +291 -291
  30. package/lib/Socket/privacy.js +77 -265
  31. package/lib/Socket/registration.js +164 -157
  32. package/lib/Socket/socket.js +181 -199
  33. package/lib/Socket/username.js +144 -227
  34. package/lib/Store/make-cache-manager-store.js +2 -2
  35. package/lib/Store/make-in-memory-store.js +25 -141
  36. package/lib/Types/Auth.js +3 -3
  37. package/lib/Types/Label.js +1 -1
  38. package/lib/Types/LabelAssociation.js +1 -1
  39. package/lib/Types/Newsletter.js +96 -65
  40. package/lib/Types/State.js +4 -4
  41. package/lib/Types/index.js +1 -1
  42. package/lib/Utils/auth-utils.js +52 -57
  43. package/lib/Utils/browser-utils.js +1 -1
  44. package/lib/Utils/business.js +2 -6
  45. package/lib/Utils/chat-utils.js +102 -38
  46. package/lib/Utils/crypto.js +54 -84
  47. package/lib/Utils/decode-wa-message.js +316 -83
  48. package/lib/Utils/event-buffer.js +37 -61
  49. package/lib/Utils/generics.js +157 -103
  50. package/lib/Utils/group-history.js +3 -12
  51. package/lib/Utils/history.js +15 -15
  52. package/lib/Utils/index.js +1 -5
  53. package/lib/Utils/link-preview.js +3 -8
  54. package/lib/Utils/lt-hash.js +2 -35
  55. package/lib/Utils/make-mutex.js +1 -1
  56. package/lib/Utils/message-inspect.js +393 -0
  57. package/lib/Utils/message-retry-manager.js +27 -92
  58. package/lib/Utils/messages-media.js +159 -130
  59. package/lib/Utils/messages.js +144 -566
  60. package/lib/Utils/meta-ai-msmsg.js +62 -202
  61. package/lib/Utils/noise-handler.js +19 -21
  62. package/lib/Utils/offline-node-processor.js +3 -8
  63. package/lib/Utils/pre-key-manager.js +13 -23
  64. package/lib/Utils/process-message.js +197 -106
  65. package/lib/Utils/reporting-utils.js +2 -2
  66. package/lib/Utils/signal.js +28 -63
  67. package/lib/Utils/stanza-ack.js +39 -12
  68. package/lib/Utils/sync-action-utils.js +4 -7
  69. package/lib/Utils/tc-token-utils.js +20 -25
  70. package/lib/Utils/use-multi-file-auth-state.js +30 -14
  71. package/lib/Utils/validate-connection.js +59 -19
  72. package/lib/WABinary/decode.js +50 -16
  73. package/lib/WABinary/encode.js +54 -224
  74. package/lib/WABinary/generic-utils.js +7 -97
  75. package/lib/WABinary/jid-utils.js +27 -14
  76. package/lib/WAM/encode.js +7 -7
  77. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +58 -1
  78. package/lib/WAUSync/Protocols/USyncContactProtocol.js +7 -1
  79. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +13 -5
  80. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +1 -4
  81. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +20 -7
  82. package/lib/WAUSync/Protocols/USyncNewsletterProtocol.js +865 -0
  83. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +1 -1
  84. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +2 -2
  85. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +7 -2
  86. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +1 -1
  87. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +2 -1
  88. package/lib/WAUSync/Protocols/index.js +1 -0
  89. package/lib/WAUSync/USyncBackoff.js +26 -0
  90. package/lib/WAUSync/USyncQuery.js +77 -6
  91. package/lib/WAUSync/USyncUser.js +16 -8
  92. package/lib/WAUSync/index.js +1 -0
  93. package/lib/antiban.js +608 -854
  94. package/lib/index.js +3 -3
  95. package/package.json +16 -19
  96. package/lib/Socket/luxu.js +0 -387
  97. package/lib/Socket/text-router.js +0 -83
  98. package/lib/Store/keyed-db.js +0 -108
  99. package/lib/Types/Mex.js +0 -112
  100. package/lib/Utils/command-loader.d.ts +0 -31
  101. package/lib/Utils/command-loader.js +0 -100
  102. package/lib/Utils/companion-reg-client-utils.js +0 -42
  103. package/lib/Utils/curve25519-js.js +0 -275
  104. package/lib/Utils/native-bridge.js +0 -82
  105. package/lib/Utils/session-pool.d.ts +0 -16
  106. package/lib/Utils/session-pool.js +0 -94
  107. package/lib/Utils/sticker.d.ts +0 -17
  108. package/lib/Utils/sticker.js +0 -145
  109. package/lib/Utils/view-once-cache.d.ts +0 -9
  110. package/lib/Utils/view-once-cache.js +0 -79
package/lib/antiban.js CHANGED
@@ -23,17 +23,17 @@ var __copyProps = (to, from, except, desc) => {
23
23
  var __toESM = (mod, isNodeMode, target) => (
24
24
  (target = mod != null ? __create(__getProtoOf(mod)) : {}),
25
25
  __copyProps(
26
- // If the importer is in node compatibility mode or this is not an ESM
27
- // file that has been converted to a CommonJS file using a Babel-
28
- // compatible transform (i.e. "__esModule" has not been set), then set
29
- // "default" to the CommonJS "module.exports" for node compatibility.
26
+
27
+
28
+
29
+
30
30
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, 'default', { value: mod, enumerable: true }) : target,
31
31
  mod
32
32
  )
33
33
  )
34
34
  var __toCommonJS = mod => __copyProps(__defProp({}, '__esModule', { value: true }), mod)
35
35
 
36
- // index.js
36
+
37
37
  var index_exports = {}
38
38
  __export(index_exports, {
39
39
  AntiBan: () => AntiBan,
@@ -61,6 +61,7 @@ __export(index_exports, {
61
61
  WebhookAlerts: () => WebhookAlerts,
62
62
  applyFingerprint: () => applyFingerprint,
63
63
  applyGroupMultiplier: () => applyGroupMultiplier,
64
+ buildContentSignature: () => buildContentSignature,
64
65
  classifyDisconnect: () => classifyDisconnect,
65
66
  createLidFirstResolver: () => createLidFirstResolver,
66
67
  credsSnapshot: () => credsSnapshot,
@@ -82,46 +83,44 @@ __export(index_exports, {
82
83
  })
83
84
  module.exports = __toCommonJS(index_exports)
84
85
 
85
- // rateLimiter.js
86
+
86
87
  var TIME_CONSTANTS = {
87
88
  MS_PER_SECOND: 1e3,
88
89
  MS_PER_MINUTE: 6e4,
89
90
  MS_PER_HOUR: 36e5,
90
91
  MS_PER_DAY: 864e5,
91
92
  BURST_RESET_MS: 3e4,
92
- IDENTICAL_WINDOW_MS: 36e5
93
- // 1 hour
93
+ IDENTICAL_WINDOW_MS: 18e5
94
+
94
95
  }
95
96
  var DEFAULT_CONFIG = {
96
- maxPerMinute: 8,
97
- maxPerHour: 200,
98
- maxPerDay: 1500,
99
- minDelayMs: 1500,
100
- maxDelayMs: 5e3,
101
- newChatDelayMs: 3e3,
102
- maxIdenticalMessages: 3,
103
- burstAllowance: 3,
97
+ maxPerMinute: 12,
98
+ maxPerHour: 400,
99
+ maxPerDay: 2500,
100
+ minDelayMs: 1200,
101
+ maxDelayMs: 4e3,
102
+ newChatDelayMs: 2e3,
103
+ maxIdenticalMessages: 10,
104
+ burstAllowance: 5,
104
105
  identicalMessageWindowMs: TIME_CONSTANTS.IDENTICAL_WINDOW_MS
105
106
  }
106
107
  var RateLimiter = class {
107
108
  config
108
109
  messages = []
109
- identicalCount = /* @__PURE__ */ new Map()
110
- knownChats = /* @__PURE__ */ new Set()
110
+ identicalCount = new Map()
111
+ knownChats = new Set()
111
112
  burstCount = 0
112
113
  lastMessageTime = 0
114
+ statsCacheTime = 0
115
+ statsCache = null
113
116
  constructor(config = {}) {
114
117
  this.config = { ...DEFAULT_CONFIG, ...config }
115
118
  }
116
- /**
117
- * Calculate delay before next message can be sent.
118
- * Returns 0 if message can be sent immediately.
119
- * Returns -1 if message should be blocked entirely.
120
- */
121
- async getDelay(recipient, content) {
119
+
120
+ async getDelay(recipient, content, dedupKey) {
122
121
  const now = Date.now()
123
122
  this.cleanup(now)
124
- const contentHash = this.hashContent(content)
123
+ const contentHash = this.hashContent(dedupKey !== undefined ? dedupKey : content)
125
124
  const dayMessages = this.messages.filter(m => now - m.timestamp < TIME_CONSTANTS.MS_PER_DAY)
126
125
  if (dayMessages.length >= this.config.maxPerDay) {
127
126
  return -1
@@ -167,16 +166,14 @@ var RateLimiter = class {
167
166
  if (timeSinceLast < this.config.minDelayMs) {
168
167
  delay = Math.max(delay, this.config.minDelayMs - timeSinceLast)
169
168
  }
170
- const typingDelay = Math.min(content.length * 30, 3e3)
169
+ const typingDelay = Math.min((content?.length || 0) * 15, 2e3)
171
170
  delay += this.jitter(typingDelay * 0.5, typingDelay)
172
171
  return Math.round(delay)
173
172
  }
174
- /**
175
- * Record a sent message
176
- */
177
- record(recipient, content) {
173
+
174
+ record(recipient, content, dedupKey) {
178
175
  const now = Date.now()
179
- const contentHash = this.hashContent(content)
176
+ const contentHash = this.hashContent(dedupKey !== undefined ? dedupKey : content)
180
177
  const timeSinceLast = now - this.lastMessageTime
181
178
  if (timeSinceLast > TIME_CONSTANTS.BURST_RESET_MS) {
182
179
  this.burstCount = 0
@@ -196,16 +193,26 @@ var RateLimiter = class {
196
193
  this.identicalCount.set(contentHash, { count: 1, firstSeen: now, lastSeen: now })
197
194
  }
198
195
  }
199
- /**
200
- * Get current usage stats
201
- */
196
+
202
197
  getStats() {
203
198
  const now = Date.now()
199
+ if (this.statsCache && now - this.statsCacheTime < 100) {
200
+ return this.statsCache
201
+ }
204
202
  this.cleanup(now)
205
- return {
206
- lastMinute: this.messages.filter(m => now - m.timestamp < TIME_CONSTANTS.MS_PER_MINUTE).length,
207
- lastHour: this.messages.filter(m => now - m.timestamp < TIME_CONSTANTS.MS_PER_HOUR).length,
208
- lastDay: this.messages.filter(m => now - m.timestamp < TIME_CONSTANTS.MS_PER_DAY).length,
203
+ let lastMinute = 0
204
+ let lastHour = 0
205
+ let lastDay = 0
206
+ for (const m of this.messages) {
207
+ const age = now - m.timestamp
208
+ if (age < TIME_CONSTANTS.MS_PER_MINUTE) lastMinute++
209
+ if (age < TIME_CONSTANTS.MS_PER_HOUR) lastHour++
210
+ if (age < TIME_CONSTANTS.MS_PER_DAY) lastDay++
211
+ }
212
+ this.statsCache = {
213
+ lastMinute,
214
+ lastHour,
215
+ lastDay,
209
216
  limits: {
210
217
  perMinute: this.config.maxPerMinute,
211
218
  perHour: this.config.maxPerHour,
@@ -213,12 +220,14 @@ var RateLimiter = class {
213
220
  },
214
221
  knownChats: this.knownChats.size
215
222
  }
223
+ this.statsCacheTime = now
224
+ return this.statsCache
216
225
  }
217
- /** Get the set of known chat JIDs (for state persistence) */
226
+
218
227
  getKnownChats() {
219
228
  return this.knownChats
220
229
  }
221
- /** Restore known chats from persisted state */
230
+
222
231
  restoreKnownChats(chats) {
223
232
  for (const jid of chats) {
224
233
  this.knownChats.add(jid)
@@ -232,7 +241,7 @@ var RateLimiter = class {
232
241
  }
233
242
  }
234
243
  }
235
- /** Random delay between min and max (gaussian-ish distribution) */
244
+
236
245
  jitter(min, max) {
237
246
  const u1 = Math.random()
238
247
  const u2 = Math.random()
@@ -241,7 +250,7 @@ var RateLimiter = class {
241
250
  const clamped = Math.max(0, Math.min(1, normalized))
242
251
  return Math.round(min + clamped * (max - min))
243
252
  }
244
- /** Simple hash for content dedup */
253
+
245
254
  hashContent(content) {
246
255
  let hash = 0
247
256
  for (let i = 0; i < content.length; i++) {
@@ -253,12 +262,12 @@ var RateLimiter = class {
253
262
  }
254
263
  }
255
264
 
256
- // warmup.js
265
+
257
266
  var DEFAULT_CONFIG2 = {
258
- warmUpDays: 7,
259
- day1Limit: 20,
267
+ warmUpDays: 5,
268
+ day1Limit: 30,
260
269
  growthFactor: 1.8,
261
- inactivityThresholdHours: 72
270
+ inactivityThresholdHours: 168
262
271
  }
263
272
  var WarmUp = class {
264
273
  config
@@ -267,9 +276,7 @@ var WarmUp = class {
267
276
  this.config = { ...DEFAULT_CONFIG2, ...config }
268
277
  this.state = existingState || this.freshState()
269
278
  }
270
- /**
271
- * Get the current daily message limit based on warm-up phase
272
- */
279
+
273
280
  getDailyLimit() {
274
281
  if (this.state.graduated) return Infinity
275
282
  const day = this.getCurrentDay()
@@ -279,9 +286,7 @@ var WarmUp = class {
279
286
  }
280
287
  return Math.round(this.config.day1Limit * Math.pow(this.config.growthFactor, day))
281
288
  }
282
- /**
283
- * Check if a message can be sent (within warm-up limits)
284
- */
289
+
285
290
  canSend() {
286
291
  this.checkInactivity()
287
292
  if (this.state.graduated) return true
@@ -289,9 +294,7 @@ var WarmUp = class {
289
294
  const todayCount = this.state.dailyCounts[day] || 0
290
295
  return todayCount < this.getDailyLimit()
291
296
  }
292
- /**
293
- * Record a sent message
294
- */
297
+
295
298
  record() {
296
299
  const now = Date.now()
297
300
  const day = this.getCurrentDay()
@@ -301,9 +304,7 @@ var WarmUp = class {
301
304
  this.state.dailyCounts[day]++
302
305
  this.state.lastActiveAt = now
303
306
  }
304
- /**
305
- * Get current warm-up status
306
- */
307
+
307
308
  getStatus() {
308
309
  const day = this.getCurrentDay()
309
310
  const todaySent = this.state.dailyCounts[day] || 0
@@ -317,15 +318,11 @@ var WarmUp = class {
317
318
  progress: this.state.graduated ? 100 : Math.round((day / this.config.warmUpDays) * 100)
318
319
  }
319
320
  }
320
- /**
321
- * Export state for persistence
322
- */
321
+
323
322
  exportState() {
324
323
  return { ...this.state }
325
324
  }
326
- /**
327
- * Reset warm-up (e.g., after detected ban risk)
328
- */
325
+
329
326
  reset() {
330
327
  this.state = this.freshState()
331
328
  }
@@ -350,7 +347,7 @@ var WarmUp = class {
350
347
  }
351
348
  }
352
349
 
353
- // health.js
350
+
354
351
  var DEFAULT_CONFIG3 = {
355
352
  disconnectWarningThreshold: 3,
356
353
  disconnectCriticalThreshold: 5,
@@ -368,9 +365,7 @@ var HealthMonitor = class {
368
365
  constructor(config = {}) {
369
366
  this.config = { ...DEFAULT_CONFIG3, ...config }
370
367
  }
371
- /**
372
- * Record a disconnection event
373
- */
368
+
374
369
  recordDisconnect(reason) {
375
370
  const reasonStr = String(reason)
376
371
  if (reasonStr === '403' || reasonStr === 'forbidden') {
@@ -392,33 +387,25 @@ var HealthMonitor = class {
392
387
  }
393
388
  this.checkAndNotify()
394
389
  }
395
- /**
396
- * Record a successful reconnection
397
- */
390
+
398
391
  recordReconnect() {
399
392
  this.events.push({ type: 'reconnect', timestamp: Date.now() })
400
393
  }
401
- /**
402
- * Record a failed message send
403
- */
394
+
404
395
  recordMessageFailed(error) {
405
396
  this.events.push({ type: 'messageFailed', timestamp: Date.now(), detail: error })
406
397
  this.lastBadEventTime = Date.now()
407
398
  this.lastEventWasSevere = false
408
399
  this.checkAndNotify()
409
400
  }
410
- /**
411
- * Record a 463 reachout timelock error
412
- */
401
+
413
402
  recordReachoutTimelock(detail) {
414
403
  this.events.push({ type: 'reachoutTimelocked', timestamp: Date.now(), detail })
415
404
  this.lastBadEventTime = Date.now()
416
405
  this.lastEventWasSevere = false
417
406
  this.checkAndNotify()
418
407
  }
419
- /**
420
- * Get current health status
421
- */
408
+
422
409
  getStatus() {
423
410
  const now = Date.now()
424
411
  this.cleanup(now)
@@ -494,24 +481,18 @@ var HealthMonitor = class {
494
481
  }
495
482
  }
496
483
  }
497
- /**
498
- * Check if sending should be paused
499
- */
484
+
500
485
  isPaused() {
501
486
  if (this.paused) return true
502
487
  const status = this.getStatus()
503
488
  const riskOrder = ['low', 'medium', 'high', 'critical']
504
489
  return riskOrder.indexOf(status.risk) >= riskOrder.indexOf(this.config.autoPauseAt)
505
490
  }
506
- /**
507
- * Manually pause/resume
508
- */
491
+
509
492
  setPaused(paused) {
510
493
  this.paused = paused
511
494
  }
512
- /**
513
- * Reset all tracked events
514
- */
495
+
515
496
  reset() {
516
497
  this.events = []
517
498
  this.startTime = Date.now()
@@ -532,7 +513,7 @@ var HealthMonitor = class {
532
513
  }
533
514
  }
534
515
 
535
- // timelockGuard.js
516
+
536
517
  var DEFAULT_CONFIG4 = {
537
518
  resumeBufferMs: 1e4
538
519
  }
@@ -542,23 +523,21 @@ var TimelockGuard = class {
542
523
  isActive: false,
543
524
  errorCount: 0
544
525
  }
545
- knownChats = /* @__PURE__ */ new Set()
526
+ knownChats = new Set()
546
527
  resumeTimer = null
547
528
  timerGeneration = 0
548
- // BUG FIX 4: Track timer validity to prevent race conditions
529
+
549
530
  constructor(config = {}) {
550
531
  this.config = { ...DEFAULT_CONFIG4, ...config }
551
532
  }
552
- /**
553
- * Update timelock state from Baileys connection.update event
554
- */
533
+
555
534
  onTimelockUpdate(data) {
556
535
  const wasActive = this.state.isActive
557
536
  this.state.isActive = !!data.isActive
558
537
  this.state.enforcementType = data.enforcementType
559
538
  this.state.expiresAt = data.timeEnforcementEnds
560
539
  if (this.state.isActive && !wasActive) {
561
- this.state.detectedAt = /* @__PURE__ */ new Date()
540
+ this.state.detectedAt = new Date()
562
541
  this.state.errorCount = 0
563
542
  this.config.onTimelockDetected?.(this.getState())
564
543
  this.scheduleResume()
@@ -570,36 +549,28 @@ var TimelockGuard = class {
570
549
  this.config.onTimelockLifted?.(this.getState())
571
550
  }
572
551
  }
573
- /**
574
- * Record a 463 error from a failed send
575
- */
552
+
576
553
  record463Error() {
577
554
  this.state.errorCount++
578
555
  if (!this.state.isActive) {
579
556
  this.state.isActive = true
580
- this.state.detectedAt = /* @__PURE__ */ new Date()
557
+ this.state.detectedAt = new Date()
581
558
  this.state.expiresAt = new Date(Date.now() + 6e4)
582
559
  this.config.onTimelockDetected?.(this.getState())
583
560
  this.scheduleResume()
584
561
  }
585
562
  }
586
- /**
587
- * Register a JID as a known/existing chat (has tctoken / prior history)
588
- */
563
+
589
564
  registerKnownChat(jid) {
590
565
  this.knownChats.add(jid)
591
566
  }
592
- /**
593
- * Register multiple known chats at once (e.g. from chat list on connect)
594
- */
567
+
595
568
  registerKnownChats(jids) {
596
569
  for (const jid of jids) {
597
570
  this.knownChats.add(jid)
598
571
  }
599
572
  }
600
- /**
601
- * Check if a message to this recipient should be allowed
602
- */
573
+
603
574
  canSend(jid) {
604
575
  if (!this.state.isActive) {
605
576
  return { allowed: true }
@@ -623,15 +594,11 @@ var TimelockGuard = class {
623
594
  reason: `Reachout timelocked (${this.state.enforcementType || 'unknown'}). New contacts blocked. Expires in ${Math.ceil(expiresIn / 1e3)}s.`
624
595
  }
625
596
  }
626
- /**
627
- * Get current timelock state
628
- */
597
+
629
598
  getState() {
630
599
  return { ...this.state }
631
600
  }
632
- /**
633
- * Check if currently timelocked
634
- */
601
+
635
602
  isTimelocked() {
636
603
  if (!this.state.isActive) return false
637
604
  if (this.state.expiresAt) {
@@ -643,15 +610,11 @@ var TimelockGuard = class {
643
610
  }
644
611
  return true
645
612
  }
646
- /**
647
- * Get the set of known chat JIDs
648
- */
613
+
649
614
  getKnownChats() {
650
615
  return new Set(this.knownChats)
651
616
  }
652
- /**
653
- * Manually lift the timelock
654
- */
617
+
655
618
  lift() {
656
619
  if (this.state.isActive) {
657
620
  this.state.isActive = false
@@ -659,9 +622,7 @@ var TimelockGuard = class {
659
622
  this.config.onTimelockLifted?.(this.getState())
660
623
  }
661
624
  }
662
- /**
663
- * Reset all state
664
- */
625
+
665
626
  reset() {
666
627
  this.state = { isActive: false, errorCount: 0 }
667
628
  this.knownChats.clear()
@@ -691,7 +652,7 @@ var TimelockGuard = class {
691
652
  }
692
653
  }
693
654
 
694
- // replyRatio.js
655
+
695
656
  var DEFAULT_CONFIG5 = {
696
657
  enabled: false,
697
658
  minRatio: 0.1,
@@ -703,14 +664,11 @@ var DEFAULT_CONFIG5 = {
703
664
  }
704
665
  var ReplyRatioGuard = class {
705
666
  config
706
- contacts = /* @__PURE__ */ new Map()
667
+ contacts = new Map()
707
668
  constructor(config = {}) {
708
669
  this.config = { ...DEFAULT_CONFIG5, ...config }
709
670
  }
710
- /**
711
- * Check if message can be sent to this contact based on reply ratio.
712
- * Call before sending.
713
- */
671
+
714
672
  beforeSend(jid) {
715
673
  if (!this.config.enabled) {
716
674
  return { allowed: true }
@@ -741,18 +699,14 @@ var ReplyRatioGuard = class {
741
699
  }
742
700
  return { allowed: true }
743
701
  }
744
- /**
745
- * Record an outbound message sent to this contact.
746
- */
702
+
747
703
  recordSent(jid) {
748
704
  if (!this.config.enabled) return
749
705
  const record = this.contacts.get(jid) || { sent: 0, received: 0 }
750
706
  record.sent++
751
707
  this.contacts.set(jid, record)
752
708
  }
753
- /**
754
- * Record an inbound message received from this contact.
755
- */
709
+
756
710
  recordReceived(jid) {
757
711
  if (!this.config.enabled) return
758
712
  const record = this.contacts.get(jid) || { sent: 0, received: 0 }
@@ -760,11 +714,7 @@ var ReplyRatioGuard = class {
760
714
  delete record.cooledUntil
761
715
  this.contacts.set(jid, record)
762
716
  }
763
- /**
764
- * Suggest whether to send an auto-reply to this incoming message.
765
- * Returns { shouldReply: true, suggestedText: '👍' } if probability check passes.
766
- * Caller is responsible for actually sending the message.
767
- */
717
+
768
718
  suggestReply(jid, _msgText) {
769
719
  if (!this.config.enabled) {
770
720
  return { shouldReply: false }
@@ -779,9 +729,7 @@ var ReplyRatioGuard = class {
779
729
  }
780
730
  return { shouldReply: false }
781
731
  }
782
- /**
783
- * Get statistics for all contacts and global metrics.
784
- */
732
+
785
733
  getStats() {
786
734
  const perContact = Array.from(this.contacts.entries()).map(([jid, record]) => ({
787
735
  jid,
@@ -802,60 +750,49 @@ var ReplyRatioGuard = class {
802
750
  contactsOnCooldown
803
751
  }
804
752
  }
805
- /**
806
- * Reset all counters.
807
- */
753
+
808
754
  reset() {
809
755
  this.contacts.clear()
810
756
  }
811
- /**
812
- * Export state for persistence.
813
- */
757
+
814
758
  exportState() {
815
759
  return {
816
760
  contacts: Array.from(this.contacts.entries())
817
761
  }
818
762
  }
819
- /**
820
- * Restore state from persistence.
821
- */
763
+
822
764
  restoreState(state) {
823
765
  if (state?.contacts && Array.isArray(state.contacts)) {
824
766
  this.contacts = new Map(state.contacts)
825
767
  }
826
768
  }
827
- /**
828
- * Check if JID is a group.
829
- */
769
+
830
770
  isGroup(jid) {
831
771
  return jid.endsWith('@g.us')
832
772
  }
833
773
  }
834
774
 
835
- // contactGraph.js
775
+
836
776
  var DEFAULT_CONFIG6 = {
837
777
  enabled: false,
838
778
  requireHandshakeBeforeGroupSend: true,
839
779
  handshakeMinDelayMs: 36e5,
840
- // 1 hour
780
+
841
781
  groupLurkPeriodMs: 432e5,
842
- // 12 hours
782
+
843
783
  maxStrangerMessagesPerDay: 5,
844
784
  autoRegisterOnIncoming: true
845
785
  }
846
786
  var ContactGraphWarmer = class {
847
787
  config
848
- contacts = /* @__PURE__ */ new Map()
849
- groups = /* @__PURE__ */ new Map()
788
+ contacts = new Map()
789
+ groups = new Map()
850
790
  strangerMessagesToday = 0
851
791
  lastStrangerResetDay = this.getCurrentDay()
852
792
  constructor(config = {}) {
853
793
  this.config = { ...DEFAULT_CONFIG6, ...config }
854
794
  }
855
- /**
856
- * Check if message can be sent to this contact/group.
857
- * Returns { allowed: false, needsHandshake: true } if handshake required.
858
- */
795
+
859
796
  canMessage(jid) {
860
797
  if (!this.config.enabled) {
861
798
  return { allowed: true }
@@ -870,9 +807,7 @@ var ContactGraphWarmer = class {
870
807
  }
871
808
  return this.checkIndividualMessage(jid)
872
809
  }
873
- /**
874
- * Mark handshake as sent to this contact.
875
- */
810
+
876
811
  markHandshakeSent(jid) {
877
812
  if (!this.config.enabled) return
878
813
  if (this.isGroup(jid)) return
@@ -881,9 +816,7 @@ var ContactGraphWarmer = class {
881
816
  record.handshakeSentAt = Date.now()
882
817
  this.contacts.set(jid, record)
883
818
  }
884
- /**
885
- * Mark handshake as complete with this contact.
886
- */
819
+
887
820
  markHandshakeComplete(jid) {
888
821
  if (!this.config.enabled) return
889
822
  if (this.isGroup(jid)) return
@@ -891,9 +824,7 @@ var ContactGraphWarmer = class {
891
824
  record.state = 'handshake_complete'
892
825
  this.contacts.set(jid, record)
893
826
  }
894
- /**
895
- * Register a contact as known (skip handshake requirement).
896
- */
827
+
897
828
  registerKnownContact(jid) {
898
829
  if (!this.config.enabled) return
899
830
  if (this.isGroup(jid)) return
@@ -901,24 +832,18 @@ var ContactGraphWarmer = class {
901
832
  record.state = 'known'
902
833
  this.contacts.set(jid, record)
903
834
  }
904
- /**
905
- * Register a group join event.
906
- */
835
+
907
836
  registerGroupJoin(groupJid) {
908
837
  if (!this.config.enabled) return
909
838
  if (!this.isGroup(groupJid)) return
910
839
  this.groups.set(groupJid, { joinedAt: Date.now() })
911
840
  }
912
- /**
913
- * Get contact state.
914
- */
841
+
915
842
  getContactState(jid) {
916
843
  if (this.isGroup(jid)) return 'known'
917
844
  return this.contacts.get(jid)?.state || 'stranger'
918
845
  }
919
- /**
920
- * Handle incoming message — auto-register if enabled.
921
- */
846
+
922
847
  onIncomingMessage(jid) {
923
848
  if (!this.config.enabled) return
924
849
  if (this.isGroup(jid)) return
@@ -926,9 +851,7 @@ var ContactGraphWarmer = class {
926
851
  this.registerKnownContact(jid)
927
852
  }
928
853
  }
929
- /**
930
- * Get statistics.
931
- */
854
+
932
855
  getStats() {
933
856
  const knownContacts = Array.from(this.contacts.values()).filter(c => c.state === 'known').length
934
857
  const pendingHandshakes = Array.from(this.contacts.values()).filter(c => c.state === 'handshake_sent').length
@@ -944,18 +867,14 @@ var ContactGraphWarmer = class {
944
867
  groupsJoined
945
868
  }
946
869
  }
947
- /**
948
- * Reset all state.
949
- */
870
+
950
871
  reset() {
951
872
  this.contacts.clear()
952
873
  this.groups.clear()
953
874
  this.strangerMessagesToday = 0
954
875
  this.lastStrangerResetDay = this.getCurrentDay()
955
876
  }
956
- /**
957
- * Export state for persistence.
958
- */
877
+
959
878
  exportState() {
960
879
  return {
961
880
  contacts: Array.from(this.contacts.entries()),
@@ -964,9 +883,7 @@ var ContactGraphWarmer = class {
964
883
  lastStrangerResetDay: this.lastStrangerResetDay
965
884
  }
966
885
  }
967
- /**
968
- * Restore state from persistence.
969
- */
886
+
970
887
  restoreState(state) {
971
888
  if (state?.contacts && Array.isArray(state.contacts)) {
972
889
  this.contacts = new Map(state.contacts)
@@ -981,7 +898,7 @@ var ContactGraphWarmer = class {
981
898
  this.lastStrangerResetDay = state.lastStrangerResetDay
982
899
  }
983
900
  }
984
- // Private helpers
901
+
985
902
  isGroup(jid) {
986
903
  return jid.endsWith('@g.us')
987
904
  }
@@ -1035,7 +952,7 @@ var ContactGraphWarmer = class {
1035
952
  }
1036
953
  }
1037
954
 
1038
- // presenceChoreographer.js
955
+
1039
956
  var DEFAULT_CONFIG7 = {
1040
957
  enabled: false,
1041
958
  enableCircadianRhythm: true,
@@ -1068,60 +985,60 @@ var DEFAULT_CONFIG7 = {
1068
985
  var ACTIVITY_CURVES = {
1069
986
  office: [
1070
987
  0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1,
1071
- // 0-7: night quiet
988
+
1072
989
  0.5, 0.5,
1073
- // 8-9: morning ramp
990
+
1074
991
  0.95, 0.95,
1075
- // 10-11: morning peak
992
+
1076
993
  0.6,
1077
- // 12: lunch dip
994
+
1078
995
  0.9, 0.9, 0.9, 0.9,
1079
- // 13-16: afternoon
996
+
1080
997
  0.6, 0.6,
1081
- // 17-18: wind-down
998
+
1082
999
  0.4, 0.4,
1083
- // 19-20: evening
1000
+
1084
1001
  0.2, 0.2, 0.2, 0.2
1085
- // 21-24: taper
1002
+
1086
1003
  ],
1087
1004
  social: [
1088
1005
  0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1,
1089
- // 0-7: night quiet
1006
+
1090
1007
  0.3, 0.4,
1091
- // 8-9: slow start
1008
+
1092
1009
  0.7, 0.8,
1093
- // 10-11: ramp up
1010
+
1094
1011
  0.5,
1095
- // 12: lunch
1012
+
1096
1013
  0.7, 0.7,
1097
- // 13-14: afternoon
1014
+
1098
1015
  0.4,
1099
- // 15: tea time dip
1016
+
1100
1017
  0.8, 0.9, 0.9,
1101
- // 16-18: active
1018
+
1102
1019
  0.6,
1103
- // 19: dinner dip
1020
+
1104
1021
  0.8, 0.85, 0.9, 0.95, 1
1105
- // 20-24: evening peak
1022
+
1106
1023
  ],
1107
1024
  global: [
1108
1025
  0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
1109
- // 0-5: night
1026
+
1110
1027
  0.4, 0.4,
1111
- // 6-7: dawn dip
1028
+
1112
1029
  0.6, 0.7, 0.8, 0.8,
1113
- // 8-11: morning
1030
+
1114
1031
  0.6,
1115
- // 12: lunch
1032
+
1116
1033
  0.8, 0.8, 0.8, 0.8,
1117
- // 13-16: afternoon
1034
+
1118
1035
  0.7, 0.7,
1119
- // 17-18: evening
1036
+
1120
1037
  0.6, 0.5, 0.5, 0.5, 0.5, 0.5
1121
- // 19-24: night taper
1038
+
1122
1039
  ]
1123
1040
  }
1124
- function getCircadianMultiplier(date = /* @__PURE__ */ new Date(), profile = 'default', timezone) {
1041
+ function getCircadianMultiplier(date = new Date(), profile = 'default', timezone) {
1125
1042
  if (profile === 'always_on') {
1126
1043
  return 1
1127
1044
  }
@@ -1186,11 +1103,7 @@ var PresenceChoreographer = class {
1186
1103
  }
1187
1104
  }
1188
1105
  }
1189
- /**
1190
- * Get current activity factor (0.1 to 1.0).
1191
- * Higher = more active = shorter delays.
1192
- * If circadian disabled, returns 1.0.
1193
- */
1106
+
1194
1107
  getCurrentActivityFactor() {
1195
1108
  if (!this.config.enabled || !this.config.enableCircadianRhythm) {
1196
1109
  return 1
@@ -1199,10 +1112,7 @@ var PresenceChoreographer = class {
1199
1112
  const curve = ACTIVITY_CURVES[this.config.activityCurve]
1200
1113
  return curve[hour] || 0.5
1201
1114
  }
1202
- /**
1203
- * Check if should pause for distraction.
1204
- * Returns { pause: true, durationMs: 600000 } if probability check passes.
1205
- */
1115
+
1206
1116
  shouldPauseForDistraction() {
1207
1117
  if (!this.config.enabled) {
1208
1118
  return { pause: false, durationMs: 0 }
@@ -1214,10 +1124,7 @@ var PresenceChoreographer = class {
1214
1124
  }
1215
1125
  return { pause: false, durationMs: 0 }
1216
1126
  }
1217
- /**
1218
- * Check if should take offline gap.
1219
- * Returns { offline: true, durationMs: 600000 } if probability check passes.
1220
- */
1127
+
1221
1128
  shouldTakeOfflineGap() {
1222
1129
  if (!this.config.enabled) {
1223
1130
  return { offline: false, durationMs: 0 }
@@ -1229,12 +1136,7 @@ var PresenceChoreographer = class {
1229
1136
  }
1230
1137
  return { offline: false, durationMs: 0 }
1231
1138
  }
1232
- /**
1233
- * Check if should mark message as read.
1234
- * Returns { mark: false } if skip probability hit.
1235
- * Returns { mark: true, delayMs: 5000 } otherwise.
1236
- * Applies circadian multiplier to delay.
1237
- */
1139
+
1238
1140
  shouldMarkRead() {
1239
1141
  if (!this.config.enabled) {
1240
1142
  return { mark: true, delayMs: 0 }
@@ -1247,7 +1149,7 @@ var PresenceChoreographer = class {
1247
1149
  let delayMs = baseDelayMs
1248
1150
  if (this.config.circadian.enabled) {
1249
1151
  const circadianMultiplier = getCircadianMultiplier(
1250
- /* @__PURE__ */ new Date(),
1152
+ new Date(),
1251
1153
  this.config.circadian.profile,
1252
1154
  this.config.circadian.timezone
1253
1155
  )
@@ -1256,18 +1158,7 @@ var PresenceChoreographer = class {
1256
1158
  this.stats.readReceiptsDelayed++
1257
1159
  return { mark: true, delayMs }
1258
1160
  }
1259
- /**
1260
- * Compute realistic typing duration for a message of given length.
1261
- * Includes Gaussian WPM variance + think-pause injection + circadian timing multiplier.
1262
- * Returns a "typing plan": array of { state, durationMs } steps the caller should execute sequentially.
1263
- *
1264
- * plan = [
1265
- * { state: 'composing', durationMs: 4200 },
1266
- * { state: 'paused', durationMs: 950 }, // think pause
1267
- * { state: 'composing', durationMs: 6800 },
1268
- * { state: 'paused', durationMs: 600 }, // brief stop before send
1269
- * ]
1270
- */
1161
+
1271
1162
  computeTypingPlan(messageLength) {
1272
1163
  if (!this.config.enabled || !this.config.enableTypingModel) {
1273
1164
  return [{ state: 'composing', durationMs: this.config.typingMinMs }]
@@ -1282,7 +1173,7 @@ var PresenceChoreographer = class {
1282
1173
  let circadianMultiplier = 1
1283
1174
  if (this.config.circadian.enabled) {
1284
1175
  circadianMultiplier = getCircadianMultiplier(
1285
- /* @__PURE__ */ new Date(),
1176
+ new Date(),
1286
1177
  this.config.circadian.profile,
1287
1178
  this.config.circadian.timezone
1288
1179
  )
@@ -1325,13 +1216,7 @@ var PresenceChoreographer = class {
1325
1216
  }
1326
1217
  return plan
1327
1218
  }
1328
- /**
1329
- * Execute a typing plan against a Baileys-shaped sock with sendPresenceUpdate(state, jid).
1330
- * Awaits each step's duration. Updates stats.
1331
- *
1332
- * await choreo.executeTypingPlan(sock, jid, plan);
1333
- * await sock.sendMessage(jid, content);
1334
- */
1219
+
1335
1220
  async executeTypingPlan(sock, jid, plan, options) {
1336
1221
  this.stats.typingPlansExecuted++
1337
1222
  for (const step of plan) {
@@ -1344,9 +1229,7 @@ var PresenceChoreographer = class {
1344
1229
  this.stats.totalTypingTimeMs += step.durationMs
1345
1230
  }
1346
1231
  }
1347
- /**
1348
- * Get statistics.
1349
- */
1232
+
1350
1233
  getStats() {
1351
1234
  return {
1352
1235
  currentActivityFactor: this.getCurrentActivityFactor(),
@@ -1360,9 +1243,7 @@ var PresenceChoreographer = class {
1360
1243
  totalTypingTimeMs: this.stats.totalTypingTimeMs
1361
1244
  }
1362
1245
  }
1363
- /**
1364
- * Reset statistics.
1365
- */
1246
+
1366
1247
  reset() {
1367
1248
  this.stats = {
1368
1249
  distractionPausesInjected: 0,
@@ -1374,7 +1255,7 @@ var PresenceChoreographer = class {
1374
1255
  totalTypingTimeMs: 0
1375
1256
  }
1376
1257
  }
1377
- // Private helpers
1258
+
1378
1259
  getLocalHour() {
1379
1260
  try {
1380
1261
  const formatter = new Intl.DateTimeFormat('en-US', {
@@ -1382,13 +1263,13 @@ var PresenceChoreographer = class {
1382
1263
  hour: 'numeric',
1383
1264
  hour12: false
1384
1265
  })
1385
- const parts = formatter.formatToParts(/* @__PURE__ */ new Date())
1266
+ const parts = formatter.formatToParts( new Date())
1386
1267
  const hourPart = parts.find(p => p.type === 'hour')
1387
1268
  if (hourPart) {
1388
1269
  return parseInt(hourPart.value, 10)
1389
1270
  }
1390
1271
  } catch (error) {}
1391
- return /* @__PURE__ */ new Date().getUTCHours()
1272
+ return new Date().getUTCHours()
1392
1273
  }
1393
1274
  randomBetween(min, max) {
1394
1275
  return Math.floor(Math.random() * (max - min + 1)) + min
@@ -1396,10 +1277,7 @@ var PresenceChoreographer = class {
1396
1277
  clamp(value, min, max) {
1397
1278
  return Math.max(min, Math.min(max, value))
1398
1279
  }
1399
- /**
1400
- * Generate Gaussian sample using Box-Muller transform.
1401
- * Returns a sample from N(mean, stdDev).
1402
- */
1280
+
1403
1281
  gaussianSample(mean, stdDev) {
1404
1282
  const u1 = Math.random()
1405
1283
  const u2 = Math.random()
@@ -1411,7 +1289,7 @@ var PresenceChoreographer = class {
1411
1289
  }
1412
1290
  }
1413
1291
 
1414
- // retryTracker.js
1292
+
1415
1293
  var DEFAULT_CONFIG8 = {
1416
1294
  enabled: false,
1417
1295
  maxRetries: 5,
@@ -1420,7 +1298,7 @@ var DEFAULT_CONFIG8 = {
1420
1298
  }
1421
1299
  var RetryReasonTracker = class {
1422
1300
  config
1423
- retries = /* @__PURE__ */ new Map()
1301
+ retries = new Map()
1424
1302
  totalRetries = 0
1425
1303
  reasonCounts = {
1426
1304
  no_session: 0,
@@ -1438,10 +1316,7 @@ var RetryReasonTracker = class {
1438
1316
  constructor(config) {
1439
1317
  this.config = { ...DEFAULT_CONFIG8, ...config }
1440
1318
  }
1441
- /**
1442
- * Call when a messages.update event arrives with a status/error.
1443
- * Classifies and records the retry.
1444
- */
1319
+
1445
1320
  onMessageUpdate(update) {
1446
1321
  if (!this.config.enabled) return
1447
1322
  const msgId = update.key?.id
@@ -1450,9 +1325,7 @@ var RetryReasonTracker = class {
1450
1325
  const reason = this.classify(update.error || update)
1451
1326
  this.recordRetry(msgId, reason)
1452
1327
  }
1453
- /**
1454
- * Classify an arbitrary error object into a RetryReason
1455
- */
1328
+
1456
1329
  classify(err) {
1457
1330
  if (!err) return 'unknown'
1458
1331
  const statusCode = err.output?.statusCode || err.statusCode || err.status
@@ -1469,9 +1342,7 @@ var RetryReasonTracker = class {
1469
1342
  if (errorMsg.includes('malformed') || errorMsg.includes('invalid node')) return 'node_malformed'
1470
1343
  return 'unknown'
1471
1344
  }
1472
- /**
1473
- * Record a retry for a message
1474
- */
1345
+
1475
1346
  recordRetry(msgId, reason) {
1476
1347
  const now = Date.now()
1477
1348
  let record = this.retries.get(msgId)
@@ -1495,22 +1366,16 @@ var RetryReasonTracker = class {
1495
1366
  this.config.onSpiral(msgId, reason)
1496
1367
  }
1497
1368
  }
1498
- /**
1499
- * Should we warn the user this message is spiraling?
1500
- */
1369
+
1501
1370
  isSpiraling(msgId) {
1502
1371
  const record = this.retries.get(msgId)
1503
1372
  return record ? record.count >= this.config.spiralThreshold : false
1504
1373
  }
1505
- /**
1506
- * Reset counters for a specific message (call on successful delivery)
1507
- */
1374
+
1508
1375
  clear(msgId) {
1509
1376
  this.retries.delete(msgId)
1510
1377
  }
1511
- /**
1512
- * Get current stats
1513
- */
1378
+
1514
1379
  getStats() {
1515
1380
  return {
1516
1381
  totalRetries: this.totalRetries,
@@ -1519,9 +1384,7 @@ var RetryReasonTracker = class {
1519
1384
  activeRetries: this.retries.size
1520
1385
  }
1521
1386
  }
1522
- /**
1523
- * Clean up old retry records (>5 minutes old)
1524
- */
1387
+
1525
1388
  cleanup() {
1526
1389
  const now = Date.now()
1527
1390
  const maxAge = 5 * 60 * 1e3
@@ -1531,16 +1394,14 @@ var RetryReasonTracker = class {
1531
1394
  }
1532
1395
  }
1533
1396
  }
1534
- /**
1535
- * Destroy and clean up
1536
- */
1397
+
1537
1398
  destroy() {
1538
1399
  this.retries.clear()
1539
1400
  this.cleanup()
1540
1401
  }
1541
1402
  }
1542
1403
 
1543
- // reconnectThrottle.js
1404
+
1544
1405
  var DEFAULT_CONFIG9 = {
1545
1406
  enabled: false,
1546
1407
  rampDurationMs: 6e4,
@@ -1555,11 +1416,11 @@ var PostReconnectThrottle = class {
1555
1416
  lifetimeReconnects = 0
1556
1417
  rampTimer = null
1557
1418
  currentStep = 0
1558
- // Tracking sends in current window
1419
+
1559
1420
  sendsInCurrentWindow = 0
1560
1421
  currentWindowStart = 0
1561
1422
  WINDOW_DURATION_MS = 6e4
1562
- // 1 minute window
1423
+
1563
1424
  constructor(config) {
1564
1425
  this.config = {
1565
1426
  ...DEFAULT_CONFIG9,
@@ -1567,9 +1428,7 @@ var PostReconnectThrottle = class {
1567
1428
  baselineRatePerMinute: config?.baselineRatePerMinute || null
1568
1429
  }
1569
1430
  }
1570
- /**
1571
- * Call when connection is re-established. Starts throttle window.
1572
- */
1431
+
1573
1432
  onReconnect() {
1574
1433
  if (!this.config.enabled) return
1575
1434
  this.throttledSince = Date.now()
@@ -1583,13 +1442,9 @@ var PostReconnectThrottle = class {
1583
1442
  }
1584
1443
  this.scheduleNextRampStep()
1585
1444
  }
1586
- /**
1587
- * Call when connection drops (optional — reset state).
1588
- */
1445
+
1589
1446
  onDisconnect() {}
1590
- /**
1591
- * Schedule the next ramp step
1592
- */
1447
+
1593
1448
  scheduleNextRampStep() {
1594
1449
  if (this.currentStep >= this.config.rampSteps) {
1595
1450
  this.throttledSince = null
@@ -1602,9 +1457,7 @@ var PostReconnectThrottle = class {
1602
1457
  this.scheduleNextRampStep()
1603
1458
  }, stepDuration)
1604
1459
  }
1605
- /**
1606
- * Returns current rate multiplier (1.0 = no throttle)
1607
- */
1460
+
1608
1461
  getCurrentMultiplier() {
1609
1462
  if (!this.config.enabled || !this.throttledSince) {
1610
1463
  return 1
@@ -1617,9 +1470,7 @@ var PostReconnectThrottle = class {
1617
1470
  const multiplier = this.config.initialRateMultiplier + (1 - this.config.initialRateMultiplier) * progress
1618
1471
  return Math.min(1, multiplier)
1619
1472
  }
1620
- /**
1621
- * Checks if a send should be gated. Returns {allowed, reason, retryAfterMs?}
1622
- */
1473
+
1623
1474
  beforeSend() {
1624
1475
  if (!this.config.enabled || !this.throttledSince) {
1625
1476
  return { allowed: true }
@@ -1648,9 +1499,7 @@ var PostReconnectThrottle = class {
1648
1499
  this.throttledSendCount++
1649
1500
  return { allowed: true }
1650
1501
  }
1651
- /**
1652
- * Get current stats
1653
- */
1502
+
1654
1503
  getStats() {
1655
1504
  const multiplier = this.getCurrentMultiplier()
1656
1505
  const isThrottled = this.throttledSince !== null && multiplier < 1
@@ -1667,9 +1516,7 @@ var PostReconnectThrottle = class {
1667
1516
  lifetimeReconnects: this.lifetimeReconnects
1668
1517
  }
1669
1518
  }
1670
- /**
1671
- * Destroy and clean up timers
1672
- */
1519
+
1673
1520
  destroy() {
1674
1521
  if (this.rampTimer) {
1675
1522
  clearTimeout(this.rampTimer)
@@ -1679,7 +1526,7 @@ var PostReconnectThrottle = class {
1679
1526
  }
1680
1527
  }
1681
1528
 
1682
- // lidResolver.js
1529
+
1683
1530
  var DEFAULT_CONFIG10 = {
1684
1531
  canonical: 'pn',
1685
1532
  maxEntries: 1e4
@@ -1687,10 +1534,10 @@ var DEFAULT_CONFIG10 = {
1687
1534
  var LidResolver = class {
1688
1535
  config
1689
1536
  persistence
1690
- // Bidirectional maps: lid→pn and pn→lid
1691
- lidToPn = /* @__PURE__ */ new Map()
1692
- pnToLid = /* @__PURE__ */ new Map()
1693
- // pn → lid (for quick reverse lookup)
1537
+
1538
+ lidToPn = new Map()
1539
+ pnToLid = new Map()
1540
+
1694
1541
  stats = {
1695
1542
  learnedFromEvents: 0,
1696
1543
  lookupsServed: 0,
@@ -1703,10 +1550,7 @@ var LidResolver = class {
1703
1550
  void this.hydrate()
1704
1551
  }
1705
1552
  }
1706
- /**
1707
- * Learn from a message event. Idempotent.
1708
- * Accepts partial mappings — will use whatever fields are available.
1709
- */
1553
+
1710
1554
  learn(mapping) {
1711
1555
  let lid = mapping.lid ? this.normalizeJid(mapping.lid) : void 0
1712
1556
  let pn = mapping.pn ? this.normalizeJid(mapping.pn) : void 0
@@ -1744,10 +1588,7 @@ var LidResolver = class {
1744
1588
  void this.flush()
1745
1589
  }
1746
1590
  }
1747
- /**
1748
- * Given any form (LID or PN), return the canonical form.
1749
- * Falls back to input if unknown (no throw).
1750
- */
1591
+
1751
1592
  resolveCanonical(jid) {
1752
1593
  const normalized = this.normalizeJid(jid)
1753
1594
  if (this.config.canonical === 'pn') {
@@ -1781,9 +1622,7 @@ var LidResolver = class {
1781
1622
  return normalized
1782
1623
  }
1783
1624
  }
1784
- /**
1785
- * Lookup partner form. Returns null if unknown.
1786
- */
1625
+
1787
1626
  getLid(pn) {
1788
1627
  const normalized = this.normalizeJid(pn)
1789
1628
  const lid = this.pnToLid.get(normalized)
@@ -1804,9 +1643,7 @@ var LidResolver = class {
1804
1643
  }
1805
1644
  return null
1806
1645
  }
1807
- /**
1808
- * Full mapping for inspection
1809
- */
1646
+
1810
1647
  getMapping(jid) {
1811
1648
  const normalized = this.normalizeJid(jid)
1812
1649
  const byLid = this.lidToPn.get(normalized)
@@ -1824,9 +1661,7 @@ var LidResolver = class {
1824
1661
  }
1825
1662
  return null
1826
1663
  }
1827
- /**
1828
- * Seed from persistence (called automatically in constructor if persistence provided)
1829
- */
1664
+
1830
1665
  async hydrate() {
1831
1666
  if (!this.persistence?.load) return
1832
1667
  try {
@@ -1853,9 +1688,7 @@ var LidResolver = class {
1853
1688
  }
1854
1689
  } catch (error) {}
1855
1690
  }
1856
- /**
1857
- * Flush current map to persistence
1858
- */
1691
+
1859
1692
  async flush() {
1860
1693
  if (!this.persistence?.save) return
1861
1694
  try {
@@ -1875,9 +1708,7 @@ var LidResolver = class {
1875
1708
  canonicalForm: this.config.canonical
1876
1709
  }
1877
1710
  }
1878
- /**
1879
- * Clear everything
1880
- */
1711
+
1881
1712
  reset() {
1882
1713
  this.lidToPn.clear()
1883
1714
  this.pnToLid.clear()
@@ -1893,16 +1724,12 @@ var LidResolver = class {
1893
1724
  void this.flush()
1894
1725
  }
1895
1726
  }
1896
- // Private helpers
1897
- /**
1898
- * Normalize JID: strip device suffix `:N`
1899
- */
1727
+
1728
+
1900
1729
  normalizeJid(jid) {
1901
1730
  return jid.replace(/:\d+@/, '@')
1902
1731
  }
1903
- /**
1904
- * Evict least recently accessed mapping (LRU)
1905
- */
1732
+
1906
1733
  evictLRU() {
1907
1734
  let oldestLid = null
1908
1735
  let oldestTime = Infinity
@@ -1922,7 +1749,7 @@ var LidResolver = class {
1922
1749
  }
1923
1750
  }
1924
1751
 
1925
- // jidCanonicalizer.js
1752
+
1926
1753
  var DEFAULT_CONFIG11 = {
1927
1754
  enabled: false,
1928
1755
  canonicalizeOutbound: true,
@@ -1932,7 +1759,7 @@ var JidCanonicalizer = class {
1932
1759
  config
1933
1760
  lidResolver
1934
1761
  ownsResolver
1935
- // Track if we created the resolver (for destroy)
1762
+
1936
1763
  stats = {
1937
1764
  outboundCanonicalized: 0,
1938
1765
  outboundPassthrough: 0,
@@ -1950,15 +1777,11 @@ var JidCanonicalizer = class {
1950
1777
  this.ownsResolver = true
1951
1778
  }
1952
1779
  }
1953
- /**
1954
- * Access the underlying resolver (for cross-module sharing)
1955
- */
1780
+
1956
1781
  get resolver() {
1957
1782
  return this.lidResolver
1958
1783
  }
1959
- /**
1960
- * Called by wrapper on every outbound send. Returns canonical JID.
1961
- */
1784
+
1962
1785
  canonicalizeTarget(jid) {
1963
1786
  if (!this.config.enabled || !this.config.canonicalizeOutbound) {
1964
1787
  return jid
@@ -1971,22 +1794,7 @@ var JidCanonicalizer = class {
1971
1794
  }
1972
1795
  return canonical
1973
1796
  }
1974
- /**
1975
- * Returns a stable, canonical thread key for storage / DB indexing.
1976
- *
1977
- * Different from `canonicalizeTarget()` (which picks the right send target):
1978
- * - canonicalizeTarget('1234@lid') → '+27...@s.whatsapp.net' (best send target)
1979
- * - canonicalKey('1234@lid') → 'thread:27...' (stable thread identifier)
1980
- *
1981
- * If LID has known PN mapping → use phone-number form
1982
- * If only LID known → use LID stripped of suffix
1983
- * Always lowercase, no @-suffix, prefixed with `thread:`
1984
- *
1985
- * Apps using this as their DB key won't double-thread on LID/PN drift.
1986
- *
1987
- * @param jid - WhatsApp JID (can be PN, LID, group, or broadcast)
1988
- * @returns Stable thread key for DB indexing
1989
- */
1797
+
1990
1798
  canonicalKey(jid) {
1991
1799
  if (!jid || typeof jid !== 'string' || jid.trim() === '') {
1992
1800
  return 'thread:invalid'
@@ -2024,9 +1832,7 @@ var JidCanonicalizer = class {
2024
1832
  }
2025
1833
  return `thread:${domain}:${user}`
2026
1834
  }
2027
- /**
2028
- * Called by wrapper on messages.upsert event. Learns mappings.
2029
- */
1835
+
2030
1836
  onIncomingEvent(upsert) {
2031
1837
  if (!this.config.enabled || !this.config.learnFromEvents) {
2032
1838
  return
@@ -2035,9 +1841,7 @@ var JidCanonicalizer = class {
2035
1841
  this.learnFromMessage(msg)
2036
1842
  }
2037
1843
  }
2038
- /**
2039
- * Called by wrapper on messages.update event. Learns from sent-message refs.
2040
- */
1844
+
2041
1845
  onMessageUpdate(updates) {
2042
1846
  if (!this.config.enabled || !this.config.learnFromEvents) {
2043
1847
  return
@@ -2063,10 +1867,8 @@ var JidCanonicalizer = class {
2063
1867
  this.lidResolver.destroy()
2064
1868
  }
2065
1869
  }
2066
- // Private helpers
2067
- /**
2068
- * Extract LID↔PN mappings from a message object
2069
- */
1870
+
1871
+
2070
1872
  learnFromMessage(msg) {
2071
1873
  if (!msg.key) return
2072
1874
  this.learnFromMessageKey(msg.key)
@@ -2078,9 +1880,7 @@ var JidCanonicalizer = class {
2078
1880
  this.stats.inboundLearned++
2079
1881
  }
2080
1882
  }
2081
- /**
2082
- * Extract mappings from message.key
2083
- */
1883
+
2084
1884
  learnFromMessageKey(key) {
2085
1885
  if (!key) return
2086
1886
  if (key.participant && key.participantPn) {
@@ -2113,7 +1913,7 @@ var JidCanonicalizer = class {
2113
1913
  }
2114
1914
  }
2115
1915
 
2116
- // sessionStability.js
1916
+
2117
1917
  function classifyDisconnect(statusCode) {
2118
1918
  if (statusCode === 401 || statusCode === 440) {
2119
1919
  return {
@@ -2152,7 +1952,7 @@ function classifyDisconnect(statusCode) {
2152
1952
  category: 'recoverable',
2153
1953
  shouldReconnect: true,
2154
1954
  backoffMs: 3e4,
2155
- // 30 seconds
1955
+
2156
1956
  message: 'Precondition failed \u2014 auth state mismatch, retry after delay',
2157
1957
  code: statusCode
2158
1958
  }
@@ -2162,7 +1962,7 @@ function classifyDisconnect(statusCode) {
2162
1962
  category: 'rate-limited',
2163
1963
  shouldReconnect: true,
2164
1964
  backoffMs: 3e5,
2165
- // 5 minutes
1965
+
2166
1966
  message: 'Rate limited by WhatsApp \u2014 cool-off period required',
2167
1967
  code: statusCode
2168
1968
  }
@@ -2172,7 +1972,7 @@ function classifyDisconnect(statusCode) {
2172
1972
  category: 'rate-limited',
2173
1973
  shouldReconnect: true,
2174
1974
  backoffMs: 6e4,
2175
- // 1 minute
1975
+
2176
1976
  message: 'WhatsApp service unavailable \u2014 temporary outage',
2177
1977
  code: statusCode
2178
1978
  }
@@ -2182,7 +1982,7 @@ function classifyDisconnect(statusCode) {
2182
1982
  category: 'recoverable',
2183
1983
  shouldReconnect: true,
2184
1984
  backoffMs: 5e3,
2185
- // 5 seconds
1985
+
2186
1986
  message: 'Connection timeout \u2014 network issue, safe to retry',
2187
1987
  code: statusCode
2188
1988
  }
@@ -2192,7 +1992,7 @@ function classifyDisconnect(statusCode) {
2192
1992
  category: 'recoverable',
2193
1993
  shouldReconnect: true,
2194
1994
  backoffMs: 1e4,
2195
- // 10 seconds
1995
+
2196
1996
  message: 'WhatsApp internal error \u2014 temporary server issue',
2197
1997
  code: statusCode
2198
1998
  }
@@ -2202,7 +2002,7 @@ function classifyDisconnect(statusCode) {
2202
2002
  category: 'recoverable',
2203
2003
  shouldReconnect: true,
2204
2004
  backoffMs: 2e3,
2205
- // 2 seconds
2005
+
2206
2006
  message: 'Connection closed gracefully \u2014 safe to reconnect',
2207
2007
  code: statusCode
2208
2008
  }
@@ -2211,7 +2011,7 @@ function classifyDisconnect(statusCode) {
2211
2011
  category: 'unknown',
2212
2012
  shouldReconnect: true,
2213
2013
  backoffMs: 15e3,
2214
- // 15 seconds
2014
+
2215
2015
  message: `Unknown disconnect reason (code ${statusCode}) \u2014 reconnect with caution`,
2216
2016
  code: statusCode
2217
2017
  }
@@ -2236,16 +2036,12 @@ var SessionHealthMonitor = class {
2236
2036
  this.onDegraded = config.onDegraded
2237
2037
  this.onRecovered = config.onRecovered
2238
2038
  }
2239
- /**
2240
- * Record successful decrypt
2241
- */
2039
+
2242
2040
  recordDecryptSuccess() {
2243
2041
  this.stats.decryptSuccess++
2244
2042
  this.checkRecovery()
2245
2043
  }
2246
- /**
2247
- * Record failed decrypt (Bad MAC or similar)
2248
- */
2044
+
2249
2045
  recordDecryptFail(isBadMac = false) {
2250
2046
  this.stats.decryptFail++
2251
2047
  if (isBadMac) {
@@ -2262,9 +2058,7 @@ var SessionHealthMonitor = class {
2262
2058
  }
2263
2059
  }
2264
2060
  }
2265
- /**
2266
- * Check if session has recovered from degraded state
2267
- */
2061
+
2268
2062
  checkRecovery() {
2269
2063
  if (!this.stats.isDegraded) return
2270
2064
  const now = Date.now()
@@ -2276,15 +2070,11 @@ var SessionHealthMonitor = class {
2276
2070
  this.onRecovered?.(this.getStats())
2277
2071
  }
2278
2072
  }
2279
- /**
2280
- * Get current health stats
2281
- */
2073
+
2282
2074
  getStats() {
2283
2075
  return { ...this.stats }
2284
2076
  }
2285
- /**
2286
- * Reset all counters
2287
- */
2077
+
2288
2078
  reset() {
2289
2079
  this.stats = {
2290
2080
  decryptSuccess: 0,
@@ -2317,51 +2107,51 @@ function wrapWithSessionStability(sock, config = {}) {
2317
2107
  })
2318
2108
  }
2319
2109
 
2320
- // presets.js
2110
+
2321
2111
  var PRESETS = {
2322
2112
  conservative: {
2323
- maxPerMinute: 5,
2324
- maxPerHour: 100,
2325
- maxPerDay: 800,
2326
- minDelayMs: 2500,
2327
- maxDelayMs: 7e3,
2328
- newChatDelayMs: 4e3,
2329
- warmupDays: 10,
2330
- day1Limit: 15,
2113
+ maxPerMinute: 6,
2114
+ maxPerHour: 150,
2115
+ maxPerDay: 1000,
2116
+ minDelayMs: 2000,
2117
+ maxDelayMs: 6e3,
2118
+ newChatDelayMs: 3e3,
2119
+ warmupDays: 7,
2120
+ day1Limit: 20,
2331
2121
  growthFactor: 1.8,
2332
- inactivityThresholdHours: 72,
2333
- autoPauseAt: 'medium',
2122
+ inactivityThresholdHours: 120,
2123
+ autoPauseAt: 'high',
2334
2124
  groupMultiplier: 0.5,
2335
2125
  groupProfiles: false,
2336
2126
  logging: true
2337
2127
  },
2338
2128
  moderate: {
2339
- maxPerMinute: 10,
2340
- maxPerHour: 300,
2341
- maxPerDay: 1500,
2342
- minDelayMs: 1500,
2343
- maxDelayMs: 5e3,
2344
- newChatDelayMs: 3e3,
2345
- warmupDays: 7,
2346
- day1Limit: 20,
2129
+ maxPerMinute: 15,
2130
+ maxPerHour: 500,
2131
+ maxPerDay: 3e3,
2132
+ minDelayMs: 1e3,
2133
+ maxDelayMs: 4e3,
2134
+ newChatDelayMs: 2e3,
2135
+ warmupDays: 5,
2136
+ day1Limit: 30,
2347
2137
  growthFactor: 1.8,
2348
- inactivityThresholdHours: 72,
2349
- autoPauseAt: 'high',
2138
+ inactivityThresholdHours: 168,
2139
+ autoPauseAt: 'critical',
2350
2140
  groupMultiplier: 0.7,
2351
2141
  groupProfiles: false,
2352
2142
  logging: true
2353
2143
  },
2354
2144
  aggressive: {
2355
- maxPerMinute: 20,
2356
- maxPerHour: 800,
2357
- maxPerDay: 4e3,
2358
- minDelayMs: 800,
2359
- maxDelayMs: 3e3,
2360
- newChatDelayMs: 2e3,
2361
- warmupDays: 4,
2362
- day1Limit: 35,
2145
+ maxPerMinute: 25,
2146
+ maxPerHour: 1200,
2147
+ maxPerDay: 6e3,
2148
+ minDelayMs: 600,
2149
+ maxDelayMs: 2500,
2150
+ newChatDelayMs: 1500,
2151
+ warmupDays: 3,
2152
+ day1Limit: 50,
2363
2153
  growthFactor: 2,
2364
- inactivityThresholdHours: 48,
2154
+ inactivityThresholdHours: 96,
2365
2155
  autoPauseAt: 'critical',
2366
2156
  groupMultiplier: 0.9,
2367
2157
  groupProfiles: false,
@@ -2370,7 +2160,7 @@ var PRESETS = {
2370
2160
  }
2371
2161
  function resolveConfig(input) {
2372
2162
  if (input === void 0) {
2373
- return { ...PRESETS.conservative }
2163
+ return { ...PRESETS.moderate }
2374
2164
  }
2375
2165
  if (typeof input === 'string') {
2376
2166
  if (!(input in PRESETS)) {
@@ -2378,14 +2168,14 @@ function resolveConfig(input) {
2378
2168
  }
2379
2169
  return { ...PRESETS[input] }
2380
2170
  }
2381
- const { preset = 'conservative', ...overrides } = input
2171
+ const { preset = 'moderate', ...overrides } = input
2382
2172
  if (!(preset in PRESETS)) {
2383
2173
  throw new Error(`Unknown preset "${preset}". Valid: ${Object.keys(PRESETS).join(', ')}`)
2384
2174
  }
2385
2175
  return { ...PRESETS[preset], ...overrides }
2386
2176
  }
2387
2177
 
2388
- // persist.js
2178
+
2389
2179
  var fs = __toESM(require('fs'), 1)
2390
2180
  var KNOWN_CHATS_MAX = 1e3
2391
2181
  var DEBOUNCE_MS = 5e3
@@ -2411,7 +2201,7 @@ var StateManager = class {
2411
2201
  return null
2412
2202
  }
2413
2203
  }
2414
- /** Debounced save — called after every send (5s delay) */
2204
+
2415
2205
  saveDebounced(state) {
2416
2206
  if (this.debounceTimer) {
2417
2207
  clearTimeout(this.debounceTimer)
@@ -2421,7 +2211,7 @@ var StateManager = class {
2421
2211
  this.debounceTimer = null
2422
2212
  }, DEBOUNCE_MS)
2423
2213
  }
2424
- /** Immediate save — called after health events (ban/restriction) */
2214
+
2425
2215
  saveImmediate(state) {
2426
2216
  if (this.debounceTimer) {
2427
2217
  clearTimeout(this.debounceTimer)
@@ -2429,7 +2219,7 @@ var StateManager = class {
2429
2219
  }
2430
2220
  this.writeFile(state)
2431
2221
  }
2432
- /** Flush/cancel pending debounced write (for tests and process exit) */
2222
+
2433
2223
  flush() {
2434
2224
  if (this.debounceTimer) {
2435
2225
  clearTimeout(this.debounceTimer)
@@ -2443,7 +2233,7 @@ var StateManager = class {
2443
2233
  const toSave = {
2444
2234
  ...state,
2445
2235
  savedAt: Date.now(),
2446
- // LRU eviction: keep last KNOWN_CHATS_MAX entries
2236
+
2447
2237
  knownChats:
2448
2238
  state.knownChats.length > KNOWN_CHATS_MAX ? state.knownChats.slice(-KNOWN_CHATS_MAX) : state.knownChats
2449
2239
  }
@@ -2455,7 +2245,7 @@ var StateManager = class {
2455
2245
  }
2456
2246
  }
2457
2247
 
2458
- // profiles.js
2248
+
2459
2249
  function isGroup(jid) {
2460
2250
  return jid.endsWith('@g.us')
2461
2251
  }
@@ -2476,26 +2266,23 @@ function applyGroupMultiplier(limits, multiplier) {
2476
2266
  }
2477
2267
  }
2478
2268
 
2479
- // antiban.js
2480
- function isLegacyConfig(cfg) {
2269
+
2270
+
2271
+
2272
+
2273
+
2274
+
2275
+
2276
+
2277
+ const CORE_LEGACY_KEYS = ['rateLimiter', 'warmUp']
2278
+ function hasLegacyCoreNesting(cfg) {
2481
2279
  if (typeof cfg !== 'object' || cfg === null) return false
2482
- return (
2483
- 'rateLimiter' in cfg ||
2484
- 'warmUp' in cfg ||
2485
- 'health' in cfg ||
2486
- 'timelock' in cfg ||
2487
- 'replyRatio' in cfg ||
2488
- 'contactGraph' in cfg ||
2489
- 'presence' in cfg ||
2490
- 'retryTracker' in cfg ||
2491
- 'reconnectThrottle' in cfg ||
2492
- 'lidResolver' in cfg ||
2493
- 'jidCanonicalizer' in cfg ||
2494
- 'sessionStability' in cfg
2495
- )
2280
+ return CORE_LEGACY_KEYS.some(key => key in cfg)
2496
2281
  }
2497
2282
  function mapLegacyToFlat(legacy) {
2498
- process.stderr.write('[baileys-antiban] DEPRECATED: Nested config (v2 style) detected. Migrate to flat config: new AntiBan({ maxPerMinute: 8 }).\n')
2283
+ process.stderr.write(
2284
+ '[baileys-antiban] DEPRECATED: nested { rateLimiter, warmUp } config detected. Migrate to flat fields: new AntiBan({ maxPerMinute: 8, warmupDays: 5 }). Flat top-level fields you also pass always take precedence.\n'
2285
+ )
2499
2286
  const flat = {}
2500
2287
  if (legacy.rateLimiter?.maxPerMinute !== void 0) flat.maxPerMinute = legacy.rateLimiter.maxPerMinute
2501
2288
  if (legacy.rateLimiter?.maxPerHour !== void 0) flat.maxPerHour = legacy.rateLimiter.maxPerHour
@@ -2506,7 +2293,6 @@ function mapLegacyToFlat(legacy) {
2506
2293
  if (legacy.warmUp?.warmUpDays !== void 0) flat.warmupDays = legacy.warmUp.warmUpDays
2507
2294
  if (legacy.warmUp?.day1Limit !== void 0) flat.day1Limit = legacy.warmUp.day1Limit
2508
2295
  if (legacy.warmUp?.growthFactor !== void 0) flat.growthFactor = legacy.warmUp.growthFactor
2509
- if (legacy.logging !== void 0) flat.logging = legacy.logging
2510
2296
  return flat
2511
2297
  }
2512
2298
  var AntiBan = class {
@@ -2531,18 +2317,29 @@ var AntiBan = class {
2531
2317
  totalDelayMs: 0
2532
2318
  }
2533
2319
  constructor(input, warmUpStateArg) {
2534
- let flatConfig
2535
- let legacyPassthrough = null
2536
2320
  let warmUpState = warmUpStateArg
2537
- if (isLegacyConfig(input)) {
2538
- legacyPassthrough = input
2539
- flatConfig = mapLegacyToFlat(legacyPassthrough)
2540
- } else {
2541
- flatConfig = {}
2542
- legacyPassthrough = null
2543
- }
2544
- const cfg = isLegacyConfig(input) ? resolveConfig(flatConfig) : resolveConfig(input)
2321
+
2322
+
2323
+
2324
+
2325
+ const rawInput = typeof input === 'object' && input !== null ? input : {}
2326
+ const legacyNested = hasLegacyCoreNesting(rawInput)
2327
+
2328
+ const flatMerged = legacyNested ? { ...mapLegacyToFlat(rawInput), ...rawInput } : rawInput
2329
+ const cfg = typeof input === 'string' ? resolveConfig(input) : resolveConfig(flatMerged)
2545
2330
  this.resolvedConfig = cfg
2331
+ const rateLimiterOverrides = rawInput.rateLimiter || {}
2332
+ const warmUpOverrides = rawInput.warmUp || {}
2333
+ const healthOverrides = rawInput.health || {}
2334
+ const timelockOverrides = rawInput.timelock || {}
2335
+ const replyRatioCfg = rawInput.replyRatio
2336
+ const contactGraphCfg = rawInput.contactGraph
2337
+ const presenceCfg = rawInput.presence
2338
+ const retryTrackerCfg = rawInput.retryTracker
2339
+ const reconnectThrottleCfg = rawInput.reconnectThrottle
2340
+ const lidResolverCfg = rawInput.lidResolver
2341
+ const jidCanonicalizerCfg = rawInput.jidCanonicalizer
2342
+ const sessionStabilityCfg = rawInput.sessionStability
2546
2343
  let savedState = null
2547
2344
  if (cfg.persist) {
2548
2345
  this.stateManager = new StateManager(cfg.persist)
@@ -2552,7 +2349,9 @@ var AntiBan = class {
2552
2349
  }
2553
2350
  }
2554
2351
  this.logging = cfg.logging ?? true
2555
- this._log = (msg) => { if (this.logging) process.stdout.write(`[antiban] ${msg}\n`) }
2352
+ this._log = msg => {
2353
+ if (this.logging) process.stdout.write(`[baileys-antiban] ${msg}\n`)
2354
+ }
2556
2355
  this.rateLimiter = new RateLimiter({
2557
2356
  maxPerMinute: cfg.maxPerMinute,
2558
2357
  maxPerHour: cfg.maxPerHour,
@@ -2560,7 +2359,7 @@ var AntiBan = class {
2560
2359
  minDelayMs: cfg.minDelayMs,
2561
2360
  maxDelayMs: cfg.maxDelayMs,
2562
2361
  newChatDelayMs: cfg.newChatDelayMs,
2563
- ...(legacyPassthrough?.rateLimiter || {})
2362
+ ...rateLimiterOverrides
2564
2363
  })
2565
2364
  if (savedState?.knownChats) {
2566
2365
  this.rateLimiter.restoreKnownChats(savedState.knownChats)
@@ -2571,69 +2370,73 @@ var AntiBan = class {
2571
2370
  day1Limit: cfg.day1Limit,
2572
2371
  growthFactor: cfg.growthFactor,
2573
2372
  inactivityThresholdHours: cfg.inactivityThresholdHours,
2574
- ...(legacyPassthrough?.warmUp || {})
2373
+ ...warmUpOverrides
2575
2374
  },
2576
2375
  warmUpState
2577
2376
  )
2578
2377
  this.health = new HealthMonitor({
2579
2378
  autoPauseAt: cfg.autoPauseAt,
2580
- ...(legacyPassthrough?.health || {}),
2379
+ ...healthOverrides,
2581
2380
  onRiskChange: status => {
2582
2381
  const emoji = { low: '\u{1F7E2}', medium: '\u{1F7E1}', high: '\u{1F7E0}', critical: '\u{1F534}' }
2583
2382
  this._log(`${emoji[status.risk]} Risk level: ${status.risk.toUpperCase()} (score: ${status.score})`)
2584
2383
  this._log(status.recommendation)
2585
2384
  status.reasons.forEach(r => this._log(` \u2192 ${r}`))
2586
- legacyPassthrough?.health?.onRiskChange?.(status)
2385
+ healthOverrides.onRiskChange?.(status)
2587
2386
  }
2588
2387
  })
2589
2388
  this.timelockGuard = new TimelockGuard({
2590
- ...(legacyPassthrough?.timelock || {}),
2389
+ ...timelockOverrides,
2591
2390
  onTimelockDetected: state => {
2592
2391
  this.health.recordReachoutTimelock(state.enforcementType)
2593
- this._log(`REACHOUT TIMELOCKED \u2014 ${state.enforcementType || 'unknown'}, expires ${state.expiresAt?.toISOString() || 'unknown'}`)
2594
- legacyPassthrough?.timelock?.onTimelockDetected?.(state)
2392
+ this._log(
2393
+ `REACHOUT TIMELOCKED \u2014 ${state.enforcementType || 'unknown'}, expires ${state.expiresAt?.toISOString() || 'unknown'}`
2394
+ )
2395
+ timelockOverrides.onTimelockDetected?.(state)
2595
2396
  },
2596
2397
  onTimelockLifted: state => {
2597
2398
  this._log('Timelock lifted \u2014 resuming new contact messages')
2598
- legacyPassthrough?.timelock?.onTimelockLifted?.(state)
2399
+ timelockOverrides.onTimelockLifted?.(state)
2599
2400
  }
2600
2401
  })
2601
- this.replyRatioGuard = new ReplyRatioGuard(legacyPassthrough?.replyRatio)
2602
- this.contactGraphWarmer = new ContactGraphWarmer(legacyPassthrough?.contactGraph)
2603
- this.presenceChoreographer = new PresenceChoreographer(legacyPassthrough?.presence)
2402
+ this.replyRatioGuard = new ReplyRatioGuard(replyRatioCfg)
2403
+ this.contactGraphWarmer = new ContactGraphWarmer(contactGraphCfg)
2404
+ this.presenceChoreographer = new PresenceChoreographer(presenceCfg)
2604
2405
  this.retryTrackerModule = new RetryReasonTracker({
2605
- ...(legacyPassthrough?.retryTracker || {}),
2406
+ ...(retryTrackerCfg || {}),
2606
2407
  onSpiral: (msgId, reason) => {
2607
2408
  this._log(`\u26A0\uFE0F Message ${msgId} stuck in retry spiral (${reason})`)
2608
- legacyPassthrough?.retryTracker?.onSpiral?.(msgId, reason)
2409
+ retryTrackerCfg?.onSpiral?.(msgId, reason)
2609
2410
  }
2610
2411
  })
2611
2412
  this.reconnectThrottleModule = new PostReconnectThrottle({
2612
- ...(legacyPassthrough?.reconnectThrottle || {}),
2413
+ ...(reconnectThrottleCfg || {}),
2613
2414
  baselineRatePerMinute: () => this.rateLimiter.getStats().limits.perMinute
2614
2415
  })
2615
- if (legacyPassthrough?.jidCanonicalizer?.enabled) {
2616
- if (legacyPassthrough.jidCanonicalizer.resolver) {
2617
- this.jidCanonicalizerModule = new JidCanonicalizer(legacyPassthrough.jidCanonicalizer)
2618
- this.lidResolverModule = legacyPassthrough.jidCanonicalizer.resolver
2416
+ if (jidCanonicalizerCfg?.enabled) {
2417
+ if (jidCanonicalizerCfg.resolver) {
2418
+ this.jidCanonicalizerModule = new JidCanonicalizer(jidCanonicalizerCfg)
2419
+ this.lidResolverModule = jidCanonicalizerCfg.resolver
2619
2420
  } else {
2620
- const resolverConfig = legacyPassthrough.lidResolver || legacyPassthrough.jidCanonicalizer.resolverConfig
2421
+ const resolverConfig = lidResolverCfg || jidCanonicalizerCfg.resolverConfig
2621
2422
  const resolver = new LidResolver(resolverConfig)
2622
2423
  this.lidResolverModule = resolver
2623
2424
  this.jidCanonicalizerModule = new JidCanonicalizer({
2624
- ...legacyPassthrough.jidCanonicalizer,
2425
+ ...jidCanonicalizerCfg,
2625
2426
  resolver
2626
2427
  })
2627
2428
  }
2628
- } else if (legacyPassthrough?.lidResolver) {
2629
- this.lidResolverModule = new LidResolver(legacyPassthrough.lidResolver)
2429
+ } else if (lidResolverCfg) {
2430
+ this.lidResolverModule = new LidResolver(lidResolverCfg)
2630
2431
  }
2631
- if (legacyPassthrough?.sessionStability?.enabled) {
2432
+ if (sessionStabilityCfg?.enabled) {
2632
2433
  const healthConfig = {
2633
- badMacThreshold: legacyPassthrough.sessionStability.badMacThreshold,
2634
- badMacWindowMs: legacyPassthrough.sessionStability.badMacWindowMs,
2434
+ badMacThreshold: sessionStabilityCfg.badMacThreshold,
2435
+ badMacWindowMs: sessionStabilityCfg.badMacWindowMs,
2635
2436
  onDegraded: stats => {
2636
- this._log(`\u{1F534} SESSION DEGRADED \u2014 Bad MAC rate: ${stats.badMacCount} in last ${legacyPassthrough?.sessionStability?.badMacWindowMs || 6e4}ms`)
2437
+ this._log(
2438
+ `\u{1F534} SESSION DEGRADED \u2014 Bad MAC rate: ${stats.badMacCount} in last ${sessionStabilityCfg.badMacWindowMs || 6e4}ms`
2439
+ )
2637
2440
  this._log('Consider restarting session or switching to LID-based canonical form')
2638
2441
  },
2639
2442
  onRecovered: () => {
@@ -2643,11 +2446,8 @@ var AntiBan = class {
2643
2446
  this.sessionStabilityMonitor = new SessionHealthMonitor(healthConfig)
2644
2447
  }
2645
2448
  }
2646
- /**
2647
- * Check if a message can be sent and get required delay.
2648
- * Call this BEFORE every sendMessage().
2649
- */
2650
- async beforeSend(recipient, content) {
2449
+
2450
+ async beforeSend(recipient, content, dedupKey) {
2651
2451
  const healthStatus = this.health.getStatus()
2652
2452
  if (this.health.isPaused()) {
2653
2453
  this.stats.messagesBlocked++
@@ -2673,7 +2473,9 @@ var AntiBan = class {
2673
2473
  if (!this.warmUp.canSend()) {
2674
2474
  this.stats.messagesBlocked++
2675
2475
  const warmUpStatus = this.warmUp.getStatus()
2676
- this._log(`\u23F3 BLOCKED \u2014 warm-up day ${warmUpStatus.day}/${warmUpStatus.totalDays}, limit reached (${warmUpStatus.todaySent}/${warmUpStatus.todayLimit})`)
2476
+ this._log(
2477
+ `\u23F3 BLOCKED \u2014 warm-up day ${warmUpStatus.day}/${warmUpStatus.totalDays}, limit reached (${warmUpStatus.todaySent}/${warmUpStatus.todayLimit})`
2478
+ )
2677
2479
  return {
2678
2480
  allowed: false,
2679
2481
  delayMs: 0,
@@ -2735,7 +2537,7 @@ var AntiBan = class {
2735
2537
  return { allowed: false, delayMs: 0, reason: 'Group rate limit exceeded', health: healthStatus }
2736
2538
  }
2737
2539
  }
2738
- let delay = await this.rateLimiter.getDelay(recipient, content)
2540
+ let delay = await this.rateLimiter.getDelay(recipient, content, dedupKey)
2739
2541
  if (delay === -1) {
2740
2542
  this.stats.messagesBlocked++
2741
2543
  this._log(`\u{1F6AB} BLOCKED \u2014 rate limit or identical message spam`)
@@ -2768,26 +2570,19 @@ var AntiBan = class {
2768
2570
  health: healthStatus
2769
2571
  }
2770
2572
  }
2771
- /**
2772
- * Record a successfully sent message.
2773
- * Call this AFTER every successful sendMessage().
2774
- */
2775
- afterSend(recipient, content) {
2776
- this.rateLimiter.record(recipient, content)
2573
+
2574
+ afterSend(recipient, content, dedupKey) {
2575
+ this.rateLimiter.record(recipient, content, dedupKey)
2777
2576
  this.warmUp.record()
2778
2577
  this.replyRatioGuard.recordSent(recipient)
2779
2578
  this.stats.messagesAllowed++
2780
2579
  this.persistStateDebounced()
2781
2580
  }
2782
- /**
2783
- * Record a failed message send
2784
- */
2581
+
2785
2582
  afterSendFailed(error) {
2786
2583
  this.health.recordMessageFailed(error)
2787
2584
  }
2788
- /**
2789
- * Record a disconnection (call from connection.update handler)
2790
- */
2585
+
2791
2586
  onDisconnect(reason) {
2792
2587
  this.health.recordDisconnect(reason)
2793
2588
  this.reconnectThrottleModule.onDisconnect()
@@ -2796,25 +2591,18 @@ var AntiBan = class {
2796
2591
  this.persistStateImmediate()
2797
2592
  }
2798
2593
  }
2799
- /**
2800
- * Record a successful reconnection
2801
- */
2594
+
2802
2595
  onReconnect() {
2803
2596
  this.health.recordReconnect()
2804
2597
  this.reconnectThrottleModule.onReconnect()
2805
2598
  }
2806
- /**
2807
- * Handle incoming message — record in reply ratio + contact graph.
2808
- * Returns suggested reply if reply ratio suggests auto-reply.
2809
- */
2599
+
2810
2600
  onIncomingMessage(jid, msgText) {
2811
2601
  this.replyRatioGuard.recordReceived(jid)
2812
2602
  this.contactGraphWarmer.onIncomingMessage(jid)
2813
2603
  return this.replyRatioGuard.suggestReply(jid, msgText)
2814
2604
  }
2815
- /**
2816
- * Get comprehensive stats
2817
- */
2605
+
2818
2606
  getStats() {
2819
2607
  const stats = {
2820
2608
  ...this.stats,
@@ -2848,65 +2636,57 @@ var AntiBan = class {
2848
2636
  }
2849
2637
  return stats
2850
2638
  }
2851
- /** Get the timelock guard for direct access */
2639
+
2852
2640
  get timelock() {
2853
2641
  return this.timelockGuard
2854
2642
  }
2855
- /** Get the reply ratio guard for direct access */
2643
+
2856
2644
  get replyRatio() {
2857
2645
  return this.replyRatioGuard
2858
2646
  }
2859
- /** Get the contact graph warmer for direct access */
2647
+
2860
2648
  get contactGraph() {
2861
2649
  return this.contactGraphWarmer
2862
2650
  }
2863
- /** Get the presence choreographer for direct access */
2651
+
2864
2652
  get presence() {
2865
2653
  return this.presenceChoreographer
2866
2654
  }
2867
- /** Get the retry tracker for direct access */
2655
+
2868
2656
  get retryTracker() {
2869
2657
  return this.retryTrackerModule
2870
2658
  }
2871
- /** Get the reconnect throttle for direct access */
2659
+
2872
2660
  get reconnectThrottle() {
2873
2661
  return this.reconnectThrottleModule
2874
2662
  }
2875
- /** Get the LID resolver for direct access */
2663
+
2876
2664
  get lidResolver() {
2877
2665
  return this.lidResolverModule
2878
2666
  }
2879
- /** Get the JID canonicalizer for direct access */
2667
+
2880
2668
  get jidCanonicalizer() {
2881
2669
  return this.jidCanonicalizerModule
2882
2670
  }
2883
- /** Get the session stability monitor for direct access */
2671
+
2884
2672
  get sessionStability() {
2885
2673
  return this.sessionStabilityMonitor
2886
2674
  }
2887
- /**
2888
- * Export warm-up state for persistence between restarts
2889
- */
2675
+
2890
2676
  exportWarmUpState() {
2891
2677
  return this.warmUp.exportState()
2892
2678
  }
2893
- /**
2894
- * Force pause all sending
2895
- */
2679
+
2896
2680
  pause() {
2897
2681
  this.health.setPaused(true)
2898
2682
  this._log('\u23F8\uFE0F Sending paused manually')
2899
2683
  }
2900
- /**
2901
- * Resume sending
2902
- */
2684
+
2903
2685
  resume() {
2904
2686
  this.health.setPaused(false)
2905
2687
  this._log('\u25B6\uFE0F Sending resumed')
2906
2688
  }
2907
- /**
2908
- * Reset everything (use after a ban period)
2909
- */
2689
+
2910
2690
  reset() {
2911
2691
  this.timelockGuard.reset()
2912
2692
  this.health.reset()
@@ -2939,10 +2719,7 @@ var AntiBan = class {
2939
2719
  }
2940
2720
  this.stateManager.saveImmediate(state)
2941
2721
  }
2942
- /**
2943
- * Clean up all timers and resources.
2944
- * Call this when disposing of the AntiBan instance or when the socket closes.
2945
- */
2722
+
2946
2723
  destroy() {
2947
2724
  this.stateManager?.destroy()
2948
2725
  this.timelockGuard.reset()
@@ -2958,17 +2735,14 @@ var AntiBan = class {
2958
2735
  }
2959
2736
  }
2960
2737
 
2961
- // lidFirstResolver.js
2738
+
2962
2739
  var fs2 = __toESM(require('fs'), 1)
2963
2740
  var path = __toESM(require('path'), 1)
2964
2741
  var LidFirstResolver = class {
2965
- lidToPhone = /* @__PURE__ */ new Map()
2966
- phoneToLid = /* @__PURE__ */ new Map()
2967
- // phone → lid (quick reverse lookup)
2968
- /**
2969
- * Load mappings from Baileys auth state directory.
2970
- * Looks for lid-mapping-*_reverse.json files.
2971
- */
2742
+ lidToPhone = new Map()
2743
+ phoneToLid = new Map()
2744
+
2745
+
2972
2746
  loadFromAuthDir(authDir) {
2973
2747
  try {
2974
2748
  if (!fs2.existsSync(authDir)) {
@@ -2998,10 +2772,7 @@ var LidFirstResolver = class {
2998
2772
  }
2999
2773
  } catch (error) {}
3000
2774
  }
3001
- /**
3002
- * Learn a new mapping from a Baileys event (messages, contacts, etc.).
3003
- * Accepts partial data — will extract what it can.
3004
- */
2775
+
3005
2776
  learnFromEvent(event) {
3006
2777
  try {
3007
2778
  if (event.key?.remoteJid) {
@@ -3020,28 +2791,19 @@ var LidFirstResolver = class {
3020
2791
  }
3021
2792
  } catch (error) {}
3022
2793
  }
3023
- /**
3024
- * Resolve phone number or phone JID to LID JID.
3025
- * Returns null if not known.
3026
- */
2794
+
3027
2795
  resolveToLID(phoneOrJid) {
3028
2796
  const phone = this.extractPhone(phoneOrJid)
3029
2797
  if (!phone) return null
3030
2798
  return this.phoneToLid.get(phone) || null
3031
2799
  }
3032
- /**
3033
- * Resolve LID JID to phone number.
3034
- * Returns null if not known.
3035
- */
2800
+
3036
2801
  resolveToPhone(lid) {
3037
2802
  const normalized = this.normalizeLid(lid)
3038
2803
  const mapping = this.lidToPhone.get(normalized)
3039
2804
  return mapping ? mapping.phone : null
3040
2805
  }
3041
- /**
3042
- * Get full mapping for a given JID (either LID or phone).
3043
- * Returns null if not known.
3044
- */
2806
+
3045
2807
  getMapping(jid) {
3046
2808
  const normalized = this.normalizeLid(jid)
3047
2809
  const byLid = this.lidToPhone.get(normalized)
@@ -3053,20 +2815,16 @@ var LidFirstResolver = class {
3053
2815
  }
3054
2816
  return null
3055
2817
  }
3056
- /**
3057
- * Get total number of known mappings.
3058
- */
2818
+
3059
2819
  size() {
3060
2820
  return this.lidToPhone.size
3061
2821
  }
3062
- /**
3063
- * Clear all mappings.
3064
- */
2822
+
3065
2823
  clear() {
3066
2824
  this.lidToPhone.clear()
3067
2825
  this.phoneToLid.clear()
3068
2826
  }
3069
- // Private helpers
2827
+
3070
2828
  learnJid(_jid, _source) {}
3071
2829
  extractPhone(jid) {
3072
2830
  if (!jid) return null
@@ -3085,7 +2843,7 @@ function createLidFirstResolver() {
3085
2843
  return new LidFirstResolver()
3086
2844
  }
3087
2845
 
3088
- // retryReason.js
2846
+
3089
2847
  var MessageRetryReason
3090
2848
  ;(function (MessageRetryReason2) {
3091
2849
  MessageRetryReason2[(MessageRetryReason2['UnknownError'] = 0)] = 'UnknownError'
@@ -3097,7 +2855,7 @@ var MessageRetryReason
3097
2855
  MessageRetryReason2[(MessageRetryReason2['MessageExpired'] = 8)] = 'MessageExpired'
3098
2856
  MessageRetryReason2[(MessageRetryReason2['DecryptionError'] = 9)] = 'DecryptionError'
3099
2857
  })(MessageRetryReason || (MessageRetryReason = {}))
3100
- var MAC_ERROR_CODES = /* @__PURE__ */ new Set([
2858
+ var MAC_ERROR_CODES = new Set([
3101
2859
  MessageRetryReason.SignalErrorBadMac,
3102
2860
  MessageRetryReason.SignalErrorInvalidMessage,
3103
2861
  MessageRetryReason.SignalErrorNoSession,
@@ -3142,133 +2900,171 @@ function getRetryReasonDescription(reason) {
3142
2900
  }
3143
2901
  }
3144
2902
 
3145
- // wrapper.js
2903
+
2904
+
2905
+ function mediaFingerprint(media) {
2906
+ if (Buffer.isBuffer(media)) {
2907
+ const len = media.length
2908
+ const head = media.subarray(0, Math.min(24, len)).toString('hex')
2909
+ const tail = len > 24 ? media.subarray(Math.max(24, len - 24)).toString('hex') : ''
2910
+ return `buf:${len}:${head}:${tail}`
2911
+ }
2912
+ if (media && typeof media === 'object' && typeof media.url === 'string') {
2913
+ return `url:${media.url}`
2914
+ }
2915
+ if (typeof media === 'string') {
2916
+ return `str:${media}`
2917
+ }
2918
+ if (media && typeof media === 'object') {
2919
+
2920
+
2921
+
2922
+ return `unresolvable:${Math.random().toString(36)}`
2923
+ }
2924
+ return 'none'
2925
+ }
2926
+
2927
+ function buildContentSignature(content) {
2928
+ if (!content || typeof content !== 'object') return String(content ?? '')
2929
+ const parts = []
2930
+ const text =
2931
+ content.text ||
2932
+ content.caption ||
2933
+ content.image?.caption ||
2934
+ content.video?.caption ||
2935
+ content.document?.caption ||
2936
+ ''
2937
+ if (text) parts.push(`text:${text}`)
2938
+ if (content.image !== undefined) parts.push(`image:${mediaFingerprint(content.image)}`)
2939
+ if (content.video !== undefined) parts.push(`video:${mediaFingerprint(content.video)}`)
2940
+ if (content.audio !== undefined) parts.push(`audio:${mediaFingerprint(content.audio)}`)
2941
+ if (content.sticker !== undefined) parts.push(`sticker:${mediaFingerprint(content.sticker)}`)
2942
+ if (content.document !== undefined) {
2943
+ parts.push(`document:${mediaFingerprint(content.document)}:${content.fileName || ''}`)
2944
+ }
2945
+ if (content.location) {
2946
+ parts.push(`location:${content.location.degreesLatitude}:${content.location.degreesLongitude}`)
2947
+ }
2948
+ if (content.contacts) {
2949
+ const vcards = content.contacts.contacts?.map(c => c.vcard).join('|') || JSON.stringify(content.contacts)
2950
+ parts.push(`contacts:${vcards}`)
2951
+ }
2952
+ if (content.poll) {
2953
+ parts.push(`poll:${content.poll.name}:${(content.poll.values || []).join(',')}`)
2954
+ }
2955
+ if (content.buttons) parts.push(`buttons:${JSON.stringify(content.buttons)}`)
2956
+ if (content.templateButtons) parts.push(`template:${JSON.stringify(content.templateButtons)}`)
2957
+ if (content.sections) parts.push(`sections:${JSON.stringify(content.sections)}`)
2958
+ if (content.react) parts.push(`react:${content.react.text}:${content.react.key?.id || ''}`)
2959
+ if (!parts.length) {
2960
+
2961
+ parts.push(`shape:${Object.keys(content).sort().join(',')}`)
2962
+ }
2963
+ return parts.join('|')
2964
+ }
3146
2965
  function wrapSocket(sock, config, warmUpState, wrapOptions) {
3147
2966
  const antiban = new AntiBan(config, warmUpState)
3148
2967
  const options = {
3149
2968
  autoRespondToIncoming: false,
3150
2969
  ...wrapOptions
3151
2970
  }
3152
- if (typeof sock.ev.process === 'function') {
3153
- sock.ev.process(async events => {
3154
- if (events['connection.update']) {
3155
- const update = events['connection.update']
3156
- if (update.connection === 'close') {
3157
- const reason = update.lastDisconnect?.error?.output?.statusCode || 'unknown'
3158
- antiban.onDisconnect(reason)
3159
- }
3160
- if (update.connection === 'open') {
3161
- antiban.onReconnect()
3162
- }
3163
- if (update.reachoutTimeLock) {
3164
- antiban.timelock.onTimelockUpdate({
3165
- isActive: update.reachoutTimeLock.isActive,
3166
- timeEnforcementEnds: update.reachoutTimeLock.timeEnforcementEnds,
3167
- enforcementType: update.reachoutTimeLock.enforcementType
3168
- })
3169
- }
3170
- }
3171
- if (events['messages.update']) {
3172
- const updates = events['messages.update']
3173
- for (const update of updates) {
3174
- if (update?.update?.messageStubParameters) {
3175
- const params = update.update.messageStubParameters
3176
- if (params.includes(463) || params.includes('463')) {
3177
- antiban.timelock.record463Error()
3178
- }
3179
- }
3180
- antiban.retryTracker.onMessageUpdate(update)
2971
+
2972
+
2973
+
2974
+
2975
+ const pendingAutoReplyTimers = new Set()
2976
+ const scheduleAutoReply = (jid, suggestedText) => {
2977
+ const replyDelay = Math.floor(Math.random() * 12e3) + 3e3
2978
+ const timer = setTimeout(async () => {
2979
+ pendingAutoReplyTimers.delete(timer)
2980
+ try {
2981
+ await sock.sendMessage(jid, { text: suggestedText })
2982
+ } catch (error) {}
2983
+ }, replyDelay)
2984
+ pendingAutoReplyTimers.add(timer)
2985
+ }
2986
+ const handleConnectionUpdate = update => {
2987
+ if (update.connection === 'close') {
2988
+ const reason = update.lastDisconnect?.error?.output?.statusCode || 'unknown'
2989
+ antiban.onDisconnect(reason)
2990
+ }
2991
+ if (update.connection === 'open') {
2992
+ antiban.onReconnect()
2993
+ }
2994
+ if (update.reachoutTimeLock) {
2995
+ antiban.timelock.onTimelockUpdate({
2996
+ isActive: update.reachoutTimeLock.isActive,
2997
+ timeEnforcementEnds: update.reachoutTimeLock.timeEnforcementEnds,
2998
+ enforcementType: update.reachoutTimeLock.enforcementType
2999
+ })
3000
+ }
3001
+ }
3002
+ const handleMessagesUpdate = updates => {
3003
+ for (const update of updates) {
3004
+ if (update?.update?.messageStubParameters) {
3005
+ const params = update.update.messageStubParameters
3006
+ if (params.includes(463) || params.includes('463')) {
3007
+ antiban.timelock.record463Error()
3181
3008
  }
3182
- antiban.jidCanonicalizer?.onMessageUpdate(updates)
3183
3009
  }
3184
- if (events['messages.upsert']) {
3185
- const { messages } = events['messages.upsert']
3186
- antiban.jidCanonicalizer?.onIncomingEvent(events['messages.upsert'])
3187
- for (const msg of messages || []) {
3188
- const jid = msg.key?.remoteJid
3189
- if (!jid) continue
3190
- antiban.timelock.registerKnownChat(jid)
3191
- const isSelf = msg.key?.fromMe || false
3192
- if (isSelf) continue
3193
- const msgText =
3194
- msg.message?.conversation ||
3195
- msg.message?.extendedTextMessage?.text ||
3196
- msg.message?.imageMessage?.caption ||
3197
- msg.message?.videoMessage?.caption ||
3198
- ''
3199
- const replySuggestion = antiban.onIncomingMessage(jid, msgText)
3200
- if (options.autoRespondToIncoming && replySuggestion.shouldReply && replySuggestion.suggestedText) {
3201
- const replyDelay = Math.floor(Math.random() * 12e3) + 3e3
3202
- setTimeout(async () => {
3203
- try {
3204
- await sock.sendMessage(jid, { text: replySuggestion.suggestedText })
3205
- } catch (error) {}
3206
- }, replyDelay)
3207
- }
3208
- }
3010
+ antiban.retryTracker.onMessageUpdate(update)
3011
+ }
3012
+ antiban.jidCanonicalizer?.onMessageUpdate(updates)
3013
+ }
3014
+ const handleMessagesUpsert = upsert => {
3015
+ const { messages } = upsert
3016
+ antiban.jidCanonicalizer?.onIncomingEvent(upsert)
3017
+ for (const msg of messages || []) {
3018
+ const jid = msg.key?.remoteJid
3019
+ if (!jid) continue
3020
+ antiban.timelock.registerKnownChat(jid)
3021
+ const isSelf = msg.key?.fromMe || false
3022
+ if (isSelf) continue
3023
+ const msgText =
3024
+ msg.message?.conversation ||
3025
+ msg.message?.extendedTextMessage?.text ||
3026
+ msg.message?.imageMessage?.caption ||
3027
+ msg.message?.videoMessage?.caption ||
3028
+ ''
3029
+ const replySuggestion = antiban.onIncomingMessage(jid, msgText)
3030
+ if (options.autoRespondToIncoming && replySuggestion.shouldReply && replySuggestion.suggestedText) {
3031
+ scheduleAutoReply(jid, replySuggestion.suggestedText)
3209
3032
  }
3210
- })
3033
+ }
3034
+ }
3035
+ let stopEventBridge = () => {}
3036
+ if (typeof sock.ev.process === 'function') {
3037
+ const processListener = async events => {
3038
+ if (events['connection.update']) handleConnectionUpdate(events['connection.update'])
3039
+ if (events['messages.update']) handleMessagesUpdate(events['messages.update'])
3040
+ if (events['messages.upsert']) handleMessagesUpsert(events['messages.upsert'])
3041
+ }
3042
+ const maybeUnsubscribe = sock.ev.process(processListener)
3043
+ if (typeof maybeUnsubscribe === 'function') {
3044
+ stopEventBridge = maybeUnsubscribe
3045
+ }
3211
3046
  } else {
3212
- sock.ev.on('connection.update', update => {
3213
- if (update.connection === 'close') {
3214
- const reason = update.lastDisconnect?.error?.output?.statusCode || 'unknown'
3215
- antiban.onDisconnect(reason)
3216
- }
3217
- if (update.connection === 'open') {
3218
- antiban.onReconnect()
3219
- }
3220
- if (update.reachoutTimeLock) {
3221
- antiban.timelock.onTimelockUpdate({
3222
- isActive: update.reachoutTimeLock.isActive,
3223
- timeEnforcementEnds: update.reachoutTimeLock.timeEnforcementEnds,
3224
- enforcementType: update.reachoutTimeLock.enforcementType
3225
- })
3226
- }
3227
- })
3228
- sock.ev.on('messages.update', updates => {
3229
- for (const update of updates) {
3230
- if (update?.update?.messageStubParameters) {
3231
- const params = update.update.messageStubParameters
3232
- if (params.includes(463) || params.includes('463')) {
3233
- antiban.timelock.record463Error()
3234
- }
3235
- }
3236
- antiban.retryTracker.onMessageUpdate(update)
3237
- }
3238
- antiban.jidCanonicalizer?.onMessageUpdate(updates)
3239
- })
3240
- sock.ev.on('messages.upsert', upsert => {
3241
- const { messages } = upsert
3242
- antiban.jidCanonicalizer?.onIncomingEvent(upsert)
3243
- for (const msg of messages || []) {
3244
- const jid = msg.key?.remoteJid
3245
- if (!jid) continue
3246
- antiban.timelock.registerKnownChat(jid)
3247
- const isSelf = msg.key?.fromMe || false
3248
- if (isSelf) continue
3249
- const msgText =
3250
- msg.message?.conversation ||
3251
- msg.message?.extendedTextMessage?.text ||
3252
- msg.message?.imageMessage?.caption ||
3253
- msg.message?.videoMessage?.caption ||
3254
- ''
3255
- const replySuggestion = antiban.onIncomingMessage(jid, msgText)
3256
- if (options.autoRespondToIncoming && replySuggestion.shouldReply && replySuggestion.suggestedText) {
3257
- const replyDelay = Math.floor(Math.random() * 12e3) + 3e3
3258
- setTimeout(async () => {
3259
- try {
3260
- await sock.sendMessage(jid, { text: replySuggestion.suggestedText })
3261
- } catch (error) {}
3262
- }, replyDelay)
3263
- }
3264
- }
3265
- })
3047
+ sock.ev.on('connection.update', handleConnectionUpdate)
3048
+ sock.ev.on('messages.update', handleMessagesUpdate)
3049
+ sock.ev.on('messages.upsert', handleMessagesUpsert)
3050
+ stopEventBridge = () => {
3051
+ sock.ev.off('connection.update', handleConnectionUpdate)
3052
+ sock.ev.off('messages.update', handleMessagesUpdate)
3053
+ sock.ev.off('messages.upsert', handleMessagesUpsert)
3054
+ }
3266
3055
  }
3267
3056
  const originalSendMessage = sock.sendMessage.bind(sock)
3268
3057
  const wrappedSendMessage = async (jid, content, options2) => {
3269
3058
  const canonicalJid = antiban.jidCanonicalizer?.canonicalizeTarget(jid) || jid
3270
- const text = content?.text || content?.caption || content?.image?.caption || ''
3271
- const decision = await antiban.beforeSend(canonicalJid, text)
3059
+ const text =
3060
+ content?.text ||
3061
+ content?.caption ||
3062
+ content?.image?.caption ||
3063
+ content?.video?.caption ||
3064
+ content?.document?.caption ||
3065
+ ''
3066
+ const dedupKey = buildContentSignature(content)
3067
+ const decision = await antiban.beforeSend(canonicalJid, text, dedupKey)
3272
3068
  if (!decision.allowed) {
3273
3069
  throw new Error(`[baileys-antiban] Message blocked: ${decision.reason}`)
3274
3070
  }
@@ -3277,7 +3073,7 @@ function wrapSocket(sock, config, warmUpState, wrapOptions) {
3277
3073
  }
3278
3074
  try {
3279
3075
  const result = await originalSendMessage(canonicalJid, content, options2)
3280
- antiban.afterSend(canonicalJid, text)
3076
+ antiban.afterSend(canonicalJid, text, dedupKey)
3281
3077
  antiban.timelock.registerKnownChat(canonicalJid)
3282
3078
  if (result?.key?.id) {
3283
3079
  antiban.retryTracker.clear(result.key.id)
@@ -3291,11 +3087,17 @@ function wrapSocket(sock, config, warmUpState, wrapOptions) {
3291
3087
  const wrapped = Object.create(sock)
3292
3088
  wrapped.sendMessage = wrappedSendMessage
3293
3089
  wrapped.antiban = antiban
3294
- wrapped.antiban.destroy = antiban.destroy.bind(antiban)
3090
+ const originalDestroy = antiban.destroy.bind(antiban)
3091
+ wrapped.antiban.destroy = () => {
3092
+ stopEventBridge()
3093
+ for (const timer of pendingAutoReplyTimers) clearTimeout(timer)
3094
+ pendingAutoReplyTimers.clear()
3095
+ originalDestroy()
3096
+ }
3295
3097
  return wrapped
3296
3098
  }
3297
3099
 
3298
- // messageQueue.js
3100
+
3299
3101
  var import_events = require('events')
3300
3102
  var DEFAULT_CONFIG12 = {
3301
3103
  maxAttempts: 3,
@@ -3314,16 +3116,11 @@ var MessageQueue = class extends import_events.EventEmitter {
3314
3116
  super()
3315
3117
  this.config = { ...DEFAULT_CONFIG12, ...config }
3316
3118
  }
3317
- /**
3318
- * Set the send function (called for each message when drained)
3319
- * This should be the anti-ban wrapped sendMessage
3320
- */
3119
+
3321
3120
  setSendFunction(fn) {
3322
3121
  this.sendFn = fn
3323
3122
  }
3324
- /**
3325
- * Add a message to the queue
3326
- */
3123
+
3327
3124
  add(recipient, content, options) {
3328
3125
  if (this.queue.length >= this.config.maxQueueSize) {
3329
3126
  throw new Error(`Queue full (${this.config.maxQueueSize} messages)`)
@@ -3345,23 +3142,17 @@ var MessageQueue = class extends import_events.EventEmitter {
3345
3142
  this.emit('added', message)
3346
3143
  return id
3347
3144
  }
3348
- /**
3349
- * Add multiple messages (e.g., broadcast to many recipients)
3350
- */
3145
+
3351
3146
  addBulk(recipients, content, options) {
3352
3147
  return recipients.map(r => this.add(r, content, options))
3353
3148
  }
3354
- /**
3355
- * Start processing the queue
3356
- */
3149
+
3357
3150
  start(intervalMs = 1e3) {
3358
3151
  if (this.drainTimer) return
3359
3152
  this.drainTimer = setInterval(() => this.processNext(), intervalMs)
3360
3153
  this.emit('started')
3361
3154
  }
3362
- /**
3363
- * Stop processing
3364
- */
3155
+
3365
3156
  stop() {
3366
3157
  if (this.drainTimer) {
3367
3158
  clearInterval(this.drainTimer)
@@ -3369,16 +3160,11 @@ var MessageQueue = class extends import_events.EventEmitter {
3369
3160
  }
3370
3161
  this.emit('stopped')
3371
3162
  }
3372
- /**
3373
- * Clean up all timers and resources.
3374
- * Call this when disposing of the queue.
3375
- */
3163
+
3376
3164
  destroy() {
3377
3165
  this.stop()
3378
3166
  }
3379
- /**
3380
- * Process the next message in the queue
3381
- */
3167
+
3382
3168
  async processNext() {
3383
3169
  if (this.processing || !this.sendFn) return
3384
3170
  const now = Date.now()
@@ -3407,9 +3193,7 @@ var MessageQueue = class extends import_events.EventEmitter {
3407
3193
  this.processing = false
3408
3194
  }
3409
3195
  }
3410
- /**
3411
- * Get queue stats
3412
- */
3196
+
3413
3197
  getStats() {
3414
3198
  const now = Date.now()
3415
3199
  return {
@@ -3425,31 +3209,23 @@ var MessageQueue = class extends import_events.EventEmitter {
3425
3209
  isRunning: this.drainTimer !== null
3426
3210
  }
3427
3211
  }
3428
- /**
3429
- * Clear all messages
3430
- */
3212
+
3431
3213
  clear() {
3432
3214
  const count = this.queue.length
3433
3215
  this.queue = []
3434
3216
  this.emit('cleared', count)
3435
3217
  }
3436
- /**
3437
- * Remove a specific message
3438
- */
3218
+
3439
3219
  remove(id) {
3440
3220
  const before = this.queue.length
3441
3221
  this.queue = this.queue.filter(m => m.id !== id)
3442
3222
  return this.queue.length < before
3443
3223
  }
3444
- /**
3445
- * Export queue for persistence
3446
- */
3224
+
3447
3225
  export() {
3448
3226
  return [...this.queue]
3449
3227
  }
3450
- /**
3451
- * Import queue (e.g., after restart)
3452
- */
3228
+
3453
3229
  import(messages) {
3454
3230
  this.queue = [...messages]
3455
3231
  this.sortQueue()
@@ -3465,7 +3241,7 @@ var MessageQueue = class extends import_events.EventEmitter {
3465
3241
  }
3466
3242
  }
3467
3243
 
3468
- // contentVariator.js
3244
+
3469
3245
  var DEFAULT_CONFIG13 = {
3470
3246
  zeroWidthChars: true,
3471
3247
  punctuationVariation: true,
@@ -3474,13 +3250,13 @@ var DEFAULT_CONFIG13 = {
3474
3250
  }
3475
3251
  var ZERO_WIDTH = [
3476
3252
  '\u200B',
3477
- // zero-width space
3253
+
3478
3254
  '\u200C',
3479
- // zero-width non-joiner
3255
+
3480
3256
  '\u200D',
3481
- // zero-width joiner
3257
+
3482
3258
  '\uFEFF'
3483
- // zero-width no-break space
3259
+
3484
3260
  ]
3485
3261
  var SYNONYMS = {
3486
3262
  hello: ['hi', 'hey', 'howdy'],
@@ -3507,10 +3283,7 @@ var ContentVariator = class {
3507
3283
  constructor(config = {}) {
3508
3284
  this.config = { ...DEFAULT_CONFIG13, ...config }
3509
3285
  }
3510
- /**
3511
- * Create a unique variation of a message
3512
- * Each call produces a slightly different version
3513
- */
3286
+
3514
3287
  vary(text) {
3515
3288
  let result = text
3516
3289
  this.counter++
@@ -3531,22 +3304,15 @@ var ContentVariator = class {
3531
3304
  }
3532
3305
  return result
3533
3306
  }
3534
- /**
3535
- * Create N unique variations of a message
3536
- */
3307
+
3537
3308
  varyBulk(text, count) {
3538
3309
  const results = []
3539
- const seen = /* @__PURE__ */ new Set()
3310
+ const startCounter = this.counter
3540
3311
  for (let i = 0; i < count; i++) {
3541
- let variation = this.vary(text)
3542
- let attempts = 0
3543
- while (seen.has(variation) && attempts < 10) {
3544
- variation = this.vary(text)
3545
- attempts++
3546
- }
3547
- seen.add(variation)
3548
- results.push(variation)
3312
+ this.counter = startCounter + i
3313
+ results.push(this.vary(text))
3549
3314
  }
3315
+ this.counter = startCounter + count
3550
3316
  return results
3551
3317
  }
3552
3318
  addZeroWidth(text) {
@@ -3565,14 +3331,14 @@ var ContentVariator = class {
3565
3331
  }
3566
3332
  varyPunctuation(text) {
3567
3333
  const variations = [
3568
- // Trailing space variations
3334
+
3569
3335
  () => text + ' ',
3570
3336
  () => text + ' ',
3571
- // Period variations
3337
+
3572
3338
  () => (text.endsWith('.') ? text.slice(0, -1) : text + '.'),
3573
- // Nothing
3339
+
3574
3340
  () => text,
3575
- // Capitalize first letter variation
3341
+
3576
3342
  () => (text.charAt(0) === text.charAt(0).toUpperCase() ? text.charAt(0).toLowerCase() + text.slice(1) : text)
3577
3343
  ]
3578
3344
  return variations[this.counter % variations.length]()
@@ -3582,21 +3348,18 @@ var ContentVariator = class {
3582
3348
  return text + emojis[this.counter % emojis.length]
3583
3349
  }
3584
3350
  applySynonyms(text) {
3585
- const words = text.split(/\b/)
3586
- let replaced = false
3587
- return words
3588
- .map(word => {
3589
- if (replaced) return word
3590
- const lower = word.toLowerCase()
3591
- const synonymList = SYNONYMS[lower]
3592
- if (synonymList && Math.random() > 0.5) {
3593
- replaced = true
3594
- const synonym = synonymList[Math.floor(Math.random() * synonymList.length)]
3595
- return word[0] === word[0].toUpperCase() ? synonym.charAt(0).toUpperCase() + synonym.slice(1) : synonym
3596
- }
3597
- return word
3598
- })
3599
- .join('')
3351
+ const lower = text.toLowerCase()
3352
+ for (const key of Object.keys(SYNONYMS)) {
3353
+ const idx = lower.indexOf(key)
3354
+ if (idx === -1) continue
3355
+ const word = text.substring(idx, idx + key.length)
3356
+ if (!SYNONYMS[key] || Math.random() > 0.5) continue
3357
+ const synonym = SYNONYMS[key][Math.floor(Math.random() * SYNONYMS[key].length)]
3358
+ const replacement =
3359
+ word[0] === word[0].toUpperCase() ? synonym.charAt(0).toUpperCase() + synonym.slice(1) : synonym
3360
+ return text.substring(0, idx) + replacement + text.substring(idx + key.length)
3361
+ }
3362
+ return text
3600
3363
  }
3601
3364
  randomPositions(max, count) {
3602
3365
  const positions = []
@@ -3608,7 +3371,7 @@ var ContentVariator = class {
3608
3371
  }
3609
3372
  }
3610
3373
 
3611
- // webhooks.js
3374
+
3612
3375
  var DEFAULT_CONFIG14 = {
3613
3376
  urls: [],
3614
3377
  minRiskLevel: 'medium',
@@ -3621,9 +3384,7 @@ var WebhookAlerts = class {
3621
3384
  constructor(config = {}) {
3622
3385
  this.config = { ...DEFAULT_CONFIG14, ...config }
3623
3386
  }
3624
- /**
3625
- * Send alert if risk level warrants it
3626
- */
3387
+
3627
3388
  async alert(data) {
3628
3389
  const riskOrder = ['low', 'medium', 'high', 'critical']
3629
3390
  if (riskOrder.indexOf(data.risk) < riskOrder.indexOf(this.config.minRiskLevel)) {
@@ -3636,7 +3397,7 @@ var WebhookAlerts = class {
3636
3397
  this.lastAlertTime = now
3637
3398
  const payload = {
3638
3399
  source: 'baileys-antiban',
3639
- timestamp: /* @__PURE__ */ new Date().toISOString(),
3400
+ timestamp: new Date().toISOString(),
3640
3401
  ...data
3641
3402
  }
3642
3403
  for (const url of this.config.urls) {
@@ -3671,7 +3432,7 @@ ${data.reasons.map(r => `\u2022 ${r}`).join('\n')}`
3671
3432
  { name: 'Recommendation', value: data.recommendation },
3672
3433
  { name: 'Reasons', value: data.reasons.join('\n') }
3673
3434
  ],
3674
- timestamp: /* @__PURE__ */ new Date().toISOString()
3435
+ timestamp: new Date().toISOString()
3675
3436
  }
3676
3437
  ]
3677
3438
  }).catch(() => {})
@@ -3696,7 +3457,7 @@ ${data.reasons.map(r => `\u2022 ${r}`).join('\n')}`
3696
3457
  }
3697
3458
  }
3698
3459
 
3699
- // scheduler.js
3460
+
3700
3461
  var DEFAULT_CONFIG15 = {
3701
3462
  timezone: 'UTC',
3702
3463
  activeHours: [8, 21],
@@ -3711,18 +3472,13 @@ var Scheduler = class {
3711
3472
  constructor(config = {}) {
3712
3473
  this.config = { ...DEFAULT_CONFIG15, ...config }
3713
3474
  }
3714
- /**
3715
- * Check if now is within active hours
3716
- */
3475
+
3717
3476
  isActiveTime() {
3718
3477
  const hour = this.getCurrentHour()
3719
3478
  const [start, end] = this.config.activeHours
3720
3479
  return hour >= start && hour < end
3721
3480
  }
3722
- /**
3723
- * Get the speed multiplier for current time
3724
- * > 1 = faster, < 1 = slower, 0 = don't send
3725
- */
3481
+
3726
3482
  getSpeedFactor() {
3727
3483
  if (!this.isActiveTime()) return 0
3728
3484
  const hour = this.getCurrentHour()
@@ -3741,12 +3497,10 @@ var Scheduler = class {
3741
3497
  }
3742
3498
  return factor
3743
3499
  }
3744
- /**
3745
- * Get ms until next active window
3746
- */
3500
+
3747
3501
  msUntilActive() {
3748
3502
  if (this.isActiveTime()) return 0
3749
- const now = /* @__PURE__ */ new Date()
3503
+ const now = new Date()
3750
3504
  const hour = now.getHours()
3751
3505
  const [start] = this.config.activeHours
3752
3506
  let nextActive
@@ -3760,17 +3514,13 @@ var Scheduler = class {
3760
3514
  }
3761
3515
  return nextActive.getTime() - now.getTime()
3762
3516
  }
3763
- /**
3764
- * Adjust a delay based on current time factors
3765
- */
3517
+
3766
3518
  adjustDelay(baseDelayMs) {
3767
3519
  const factor = this.getSpeedFactor()
3768
3520
  if (factor === 0) return -1
3769
3521
  return Math.round(baseDelayMs / factor)
3770
3522
  }
3771
- /**
3772
- * Get current schedule status
3773
- */
3523
+
3774
3524
  getStatus() {
3775
3525
  const hour = this.getCurrentHour()
3776
3526
  const day = this.getCurrentDay()
@@ -3786,14 +3536,14 @@ var Scheduler = class {
3786
3536
  }
3787
3537
  }
3788
3538
  getCurrentHour() {
3789
- return /* @__PURE__ */ new Date().getHours()
3539
+ return new Date().getHours()
3790
3540
  }
3791
3541
  getCurrentDay() {
3792
- return /* @__PURE__ */ new Date().getDay()
3542
+ return new Date().getDay()
3793
3543
  }
3794
3544
  }
3795
3545
 
3796
- // stateAdapter.js
3546
+
3797
3547
  var _fsPromises = require('fs/promises')
3798
3548
  var _fsSync = require('fs')
3799
3549
  var _path3 = require('path')
@@ -3836,11 +3586,11 @@ var FileStateAdapter = class {
3836
3586
  }
3837
3587
  }
3838
3588
 
3839
- // messageRecovery.js
3589
+
3840
3590
  var DEFAULT_CONFIG16 = {
3841
3591
  maxTrackedChats: 1e3,
3842
3592
  maxGapMs: 30 * 6e4,
3843
- // 30 minutes
3593
+
3844
3594
  persistDebounceMs: 2e3,
3845
3595
  onGapFilled: () => {},
3846
3596
  logger: {
@@ -3852,7 +3602,7 @@ var DEFAULT_CONFIG16 = {
3852
3602
  function messageRecovery(sock, config) {
3853
3603
  const cfg = { ...DEFAULT_CONFIG16, ...config }
3854
3604
  const logger = cfg.logger
3855
- const lastSeen = /* @__PURE__ */ new Map()
3605
+ const lastSeen = new Map()
3856
3606
  let disconnectedAt = null
3857
3607
  let totalRecovered = 0
3858
3608
  let lastReconnectAt = null
@@ -3952,7 +3702,7 @@ function messageRecovery(sock, config) {
3952
3702
  loggedFetchWarning = true
3953
3703
  }
3954
3704
  disconnectedAt = null
3955
- lastReconnectAt = /* @__PURE__ */ new Date()
3705
+ lastReconnectAt = new Date()
3956
3706
  lastGapMs = gapMs
3957
3707
  await cfg.onRecoveryComplete?.({
3958
3708
  chats: 0,
@@ -3965,7 +3715,7 @@ function messageRecovery(sock, config) {
3965
3715
  try {
3966
3716
  const messages = await sock.fetchMessageHistory(jid, 50, {
3967
3717
  before: void 0
3968
- // Get latest
3718
+
3969
3719
  })
3970
3720
  if (!messages || !Array.isArray(messages)) continue
3971
3721
  const gapMessages = messages.filter(msg => {
@@ -3998,7 +3748,7 @@ function messageRecovery(sock, config) {
3998
3748
  }
3999
3749
  }
4000
3750
  totalRecovered += recovered
4001
- lastReconnectAt = /* @__PURE__ */ new Date()
3751
+ lastReconnectAt = new Date()
4002
3752
  lastGapMs = gapMs
4003
3753
  disconnectedAt = null
4004
3754
  logger.info?.(
@@ -4085,29 +3835,33 @@ function messageRecovery(sock, config) {
4085
3835
  }
4086
3836
  }
4087
3837
 
4088
- // deviceFingerprint.js
3838
+
4089
3839
  var DEFAULT_APP_VERSION_POOL = [
4090
- [2, 24, 5, 18],
4091
- [2, 24, 5, 17],
4092
- [2, 24, 4, 77],
4093
- [2, 24, 5, 15],
4094
- [2, 24, 3, 91],
4095
- [2, 24, 5, 20]
3840
+ [2, 25, 10, 67],
3841
+ [2, 25, 10, 68],
3842
+ [2, 25, 9, 96],
3843
+ [2, 25, 8, 77],
3844
+ [2, 25, 7, 85],
3845
+ [2, 25, 6, 98],
3846
+ [2, 24, 22, 78],
3847
+ [2, 24, 20, 86]
4096
3848
  ]
4097
- var DEFAULT_OS_VERSION_POOL = ['10', '11', '12', '13', '14']
3849
+ var DEFAULT_OS_VERSION_POOL = ['11', '12', '13', '14', '15']
4098
3850
  var DEFAULT_DEVICE_MODEL_POOL = [
4099
- 'Pixel 6',
3851
+ 'Pixel 8',
3852
+ 'Pixel 9',
4100
3853
  'Pixel 7',
4101
- 'Galaxy S22',
3854
+ 'Galaxy S24',
4102
3855
  'Galaxy S23',
3856
+ 'Galaxy S22',
3857
+ 'Xiaomi 14',
4103
3858
  'Xiaomi 13',
4104
- 'Xiaomi 12',
3859
+ 'OnePlus 12',
4105
3860
  'OnePlus 11',
4106
3861
  'Moto G84',
4107
- 'Moto G54',
4108
- 'Realme 11',
4109
- 'Vivo V29',
4110
- 'Oppo Find X6'
3862
+ 'Realme 12',
3863
+ 'Vivo V30',
3864
+ 'Oppo Find X7'
4111
3865
  ]
4112
3866
  var SeededRandom = class {
4113
3867
  state
@@ -4147,7 +3901,7 @@ function generateFingerprint(config = {}, sessionId) {
4147
3901
  const deviceModel = enabled && randomizeDeviceModel ? rng.pick(deviceModelPool) : deviceModelPool[0]
4148
3902
  return {
4149
3903
  appVersion: [...appVersion],
4150
- // Copy to avoid mutation
3904
+
4151
3905
  osVersion,
4152
3906
  deviceModel,
4153
3907
  sessionId: finalSessionId
@@ -4164,7 +3918,7 @@ function applyFingerprint(socketConfig, fp) {
4164
3918
  return config
4165
3919
  }
4166
3920
 
4167
- // credsSnapshot.js
3921
+
4168
3922
  var import_fs = require('fs')
4169
3923
  var path2 = __toESM(require('path'), 1)
4170
3924
  var noop = () => {}
@@ -4184,7 +3938,7 @@ function credsSnapshot(config) {
4184
3938
  return null
4185
3939
  }
4186
3940
  await import_fs.promises.mkdir(snapshotDir, { recursive: true })
4187
- const timestamp = /* @__PURE__ */ new Date().toISOString().replace(/[:.]/g, '-')
3941
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
4188
3942
  const snapshotPath = path2.join(snapshotDir, `creds-${timestamp}.json`)
4189
3943
  const tmpPath = `${snapshotPath}.tmp`
4190
3944
  await import_fs.promises.copyFile(credsPath, tmpPath)
@@ -4265,7 +4019,7 @@ function credsSnapshot(config) {
4265
4019
  }
4266
4020
  }
4267
4021
 
4268
- // readReceiptVariance.js
4022
+
4269
4023
  function gaussianRandom() {
4270
4024
  let u = 0
4271
4025
  let v = 0
@@ -4275,7 +4029,7 @@ function gaussianRandom() {
4275
4029
  }
4276
4030
  function readReceiptVariance(config = {}) {
4277
4031
  const { meanMs = 1500, stdDevMs = 800, minMs = 200, maxMs = 8e3, skipIfOlderThanMs = 6e4 } = config
4278
- const pendingTimers = /* @__PURE__ */ new Set()
4032
+ const pendingTimers = new Set()
4279
4033
  function delayMs() {
4280
4034
  const gaussian = gaussianRandom()
4281
4035
  const value = meanMs + gaussian * stdDevMs
@@ -4332,7 +4086,7 @@ function readReceiptVariance(config = {}) {
4332
4086
  }
4333
4087
  }
4334
4088
 
4335
- // proxyRotator.js
4089
+
4336
4090
  var import_node_module = require('node:module')
4337
4091
  var require2 = (0, import_node_module.createRequire)(__importMetaUrl)
4338
4092
  var NoopLogger = {
@@ -4348,7 +4102,7 @@ function proxyRotator(config) {
4348
4102
  scheduledIntervalMs = 0,
4349
4103
  maxFailures = 3,
4350
4104
  deadCooldownMs = 6e5,
4351
- // 10 minutes
4105
+
4352
4106
  logger = NoopLogger
4353
4107
  } = config
4354
4108
  if (!pool || pool.length === 0) {
@@ -4370,7 +4124,7 @@ function proxyRotator(config) {
4370
4124
  let totalRotations = 0
4371
4125
  const rotationsByTrigger = {}
4372
4126
  let scheduledTimer = null
4373
- const agentCache = /* @__PURE__ */ new Map()
4127
+ const agentCache = new Map()
4374
4128
  const moduleCache = {}
4375
4129
  function buildProxyUrl(endpoint) {
4376
4130
  const { type, host, port, username, password } = endpoint
@@ -4509,7 +4263,7 @@ function proxyRotator(config) {
4509
4263
  } else {
4510
4264
  currentIndex = nextIdx
4511
4265
  }
4512
- states[currentIndex].lastUsedAt = /* @__PURE__ */ new Date()
4266
+ states[currentIndex].lastUsedAt = new Date()
4513
4267
  totalRotations++
4514
4268
  rotationsByTrigger[reason] = (rotationsByTrigger[reason] || 0) + 1
4515
4269
  const label = states[currentIndex].endpoint.label || states[currentIndex].endpoint.host
@@ -4577,7 +4331,7 @@ function proxyRotator(config) {
4577
4331
  }, scheduledIntervalMs)
4578
4332
  logger.info?.(`Scheduled rotation enabled (every ${scheduledIntervalMs}ms)`)
4579
4333
  }
4580
- states[0].lastUsedAt = /* @__PURE__ */ new Date()
4334
+ states[0].lastUsedAt = new Date()
4581
4335
  return {
4582
4336
  currentAgent: currentAgentImpl,
4583
4337
  current: currentImpl,
@@ -4588,7 +4342,7 @@ function proxyRotator(config) {
4588
4342
  getStats: getStatsImpl
4589
4343
  }
4590
4344
  }
4591
- // Annotate the CommonJS export names for ESM import in node:
4345
+
4592
4346
  0 &&
4593
4347
  (module.exports = {
4594
4348
  AntiBan,