@celestial-community/baileys 0.0.1-security → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @celestial-community/baileys might be problematic. Click here for more details.

Files changed (175) hide show
  1. package/WAProto/index.js +138933 -0
  2. package/engine-requirements.js +10 -0
  3. package/lib/Defaults/baileys-version.json +7 -0
  4. package/lib/Defaults/index.js +157 -0
  5. package/lib/Defaults/phonenumber-mcc.json +223 -0
  6. package/lib/Signal/Group/ciphertext-message.js +15 -0
  7. package/lib/Signal/Group/group-session-builder.js +94 -0
  8. package/lib/Signal/Group/group_cipher.js +118 -0
  9. package/lib/Signal/Group/index.js +138 -0
  10. package/lib/Signal/Group/keyhelper.js +75 -0
  11. package/lib/Signal/Group/queue-job.js +54 -0
  12. package/lib/Signal/Group/sender-chain-key.js +39 -0
  13. package/lib/Signal/Group/sender-key-distribution-message.js +71 -0
  14. package/lib/Signal/Group/sender-key-message.js +76 -0
  15. package/lib/Signal/Group/sender-key-name.js +50 -0
  16. package/lib/Signal/Group/sender-key-record.js +65 -0
  17. package/lib/Signal/Group/sender-key-state.js +114 -0
  18. package/lib/Signal/Group/sender-message-key.js +33 -0
  19. package/lib/Signal/libsignal.js +204 -0
  20. package/lib/Signal/lid-mapping.js +267 -0
  21. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  22. package/lib/Socket/Client/index.js +32 -0
  23. package/lib/Socket/Client/mobile-socket-client.js +82 -0
  24. package/lib/Socket/Client/web-socket-client.js +89 -0
  25. package/lib/Socket/Denzy-ZeroDay.js +805 -0
  26. package/lib/Socket/business.js +279 -0
  27. package/lib/Socket/chats.js +1169 -0
  28. package/lib/Socket/community.d.ts +120 -0
  29. package/lib/Socket/community.js +388 -0
  30. package/lib/Socket/graphql.js +1122 -0
  31. package/lib/Socket/groups.js +345 -0
  32. package/lib/Socket/index.js +22 -0
  33. package/lib/Socket/interop.js +265 -0
  34. package/lib/Socket/lid-mapping.js +111 -0
  35. package/lib/Socket/messages-recv.js +1385 -0
  36. package/lib/Socket/messages-send.js +956 -0
  37. package/lib/Socket/mex.js +69 -0
  38. package/lib/Socket/newsletter.js +424 -0
  39. package/lib/Socket/privacy.js +229 -0
  40. package/lib/Socket/registration.js +190 -0
  41. package/lib/Socket/socket.js +783 -0
  42. package/lib/Socket/username.d.ts +185 -0
  43. package/lib/Socket/username.js +168 -0
  44. package/lib/Socket/usync.js +80 -0
  45. package/lib/Store/index.js +14 -0
  46. package/lib/Store/keyed-db.js +158 -0
  47. package/lib/Store/make-cache-manager-store.js +88 -0
  48. package/lib/Store/make-in-memory-store.js +484 -0
  49. package/lib/Store/make-ordered-dictionary.js +78 -0
  50. package/lib/Store/object-repository.js +27 -0
  51. package/lib/Types/Auth.js +2 -0
  52. package/lib/Types/Call.js +2 -0
  53. package/lib/Types/Chat.js +10 -0
  54. package/lib/Types/Contact.js +2 -0
  55. package/lib/Types/Events.js +2 -0
  56. package/lib/Types/GroupMetadata.js +2 -0
  57. package/lib/Types/Label.js +27 -0
  58. package/lib/Types/LabelAssociation.js +9 -0
  59. package/lib/Types/Message.js +14 -0
  60. package/lib/Types/MexUpdates.js +19 -0
  61. package/lib/Types/Newsletter.js +38 -0
  62. package/lib/Types/Product.js +2 -0
  63. package/lib/Types/RichType.js +30 -0
  64. package/lib/Types/Signal.js +2 -0
  65. package/lib/Types/Socket.js +2 -0
  66. package/lib/Types/State.js +2 -0
  67. package/lib/Types/USync.js +2 -0
  68. package/lib/Types/index.js +58 -0
  69. package/lib/Utils/anti-ban.js +339 -0
  70. package/lib/Utils/anti-delete.d.ts +158 -0
  71. package/lib/Utils/anti-delete.js +293 -0
  72. package/lib/Utils/antiban-presets.js +91 -0
  73. package/lib/Utils/antiban-profiles.js +43 -0
  74. package/lib/Utils/auth-utils.js +210 -0
  75. package/lib/Utils/baileys-event-stream.js +66 -0
  76. package/lib/Utils/browser-utils.js +52 -0
  77. package/lib/Utils/business.js +261 -0
  78. package/lib/Utils/chat-control.d.ts +113 -0
  79. package/lib/Utils/chat-control.js +230 -0
  80. package/lib/Utils/chat-utils.js +922 -0
  81. package/lib/Utils/companion-reg-client-utils.js +37 -0
  82. package/lib/Utils/contact-graph-warmer.js +208 -0
  83. package/lib/Utils/crypto.js +196 -0
  84. package/lib/Utils/decode-wa-message.js +208 -0
  85. package/lib/Utils/delivery-tracker.js +110 -0
  86. package/lib/Utils/device-fingerprint.js +135 -0
  87. package/lib/Utils/event-buffer.js +531 -0
  88. package/lib/Utils/generics.js +571 -0
  89. package/lib/Utils/group-operation-guard.js +147 -0
  90. package/lib/Utils/health-monitor.js +207 -0
  91. package/lib/Utils/history.js +122 -0
  92. package/lib/Utils/human-entropy.js +226 -0
  93. package/lib/Utils/identity-change-handler.js +72 -0
  94. package/lib/Utils/index.js +83 -0
  95. package/lib/Utils/interactive-message.d.ts +139 -0
  96. package/lib/Utils/interactive-message.js +273 -0
  97. package/lib/Utils/legitimacy-signal-injector.js +180 -0
  98. package/lib/Utils/link-preview.js +106 -0
  99. package/lib/Utils/logger.d.ts +13 -0
  100. package/lib/Utils/logger.js +9 -0
  101. package/lib/Utils/lt-hash.js +54 -0
  102. package/lib/Utils/make-mutex.js +41 -0
  103. package/lib/Utils/message-composer.d.ts +106 -0
  104. package/lib/Utils/message-composer.js +721 -0
  105. package/lib/Utils/message-retry-manager.d.ts +88 -0
  106. package/lib/Utils/message-retry-manager.js +160 -0
  107. package/lib/Utils/message-search.d.ts +52 -0
  108. package/lib/Utils/message-search.js +226 -0
  109. package/lib/Utils/messages-media.js +899 -0
  110. package/lib/Utils/messages.js +2698 -0
  111. package/lib/Utils/noise-handler.js +175 -0
  112. package/lib/Utils/offline-node-processor.js +45 -0
  113. package/lib/Utils/pre-key-manager.js +131 -0
  114. package/lib/Utils/presence-choreographer.js +438 -0
  115. package/lib/Utils/process-message.js +423 -0
  116. package/lib/Utils/rate-limiter.js +232 -0
  117. package/lib/Utils/reconnect-throttle.js +157 -0
  118. package/lib/Utils/reply-ratio-guard.js +137 -0
  119. package/lib/Utils/reporting-utils.js +307 -0
  120. package/lib/Utils/retry-reason-tracker.js +140 -0
  121. package/lib/Utils/rich-message-utils.d.ts +48 -0
  122. package/lib/Utils/rich-message-utils.js +400 -0
  123. package/lib/Utils/rich-response-utils.js +461 -0
  124. package/lib/Utils/scheduling.d.ts +135 -0
  125. package/lib/Utils/scheduling.js +246 -0
  126. package/lib/Utils/session-fingerprint.js +226 -0
  127. package/lib/Utils/session-stability.js +224 -0
  128. package/lib/Utils/signal.js +188 -0
  129. package/lib/Utils/stanza-ack.js +38 -0
  130. package/lib/Utils/state-manager.js +91 -0
  131. package/lib/Utils/status-posting.d.ts +81 -0
  132. package/lib/Utils/status-posting.js +187 -0
  133. package/lib/Utils/stealth-connect.js +124 -0
  134. package/lib/Utils/sync-action-utils.js +55 -0
  135. package/lib/Utils/tc-token-utils.js +171 -0
  136. package/lib/Utils/templates.d.ts +54 -0
  137. package/lib/Utils/templates.js +244 -0
  138. package/lib/Utils/timelock-guard.js +162 -0
  139. package/lib/Utils/use-mongo-file-auth-state.d.ts +6 -0
  140. package/lib/Utils/use-mongo-file-auth-state.js +81 -0
  141. package/lib/Utils/use-multi-file-auth-state.js +125 -0
  142. package/lib/Utils/use-single-file-auth-state.d.ts +13 -0
  143. package/lib/Utils/use-single-file-auth-state.js +86 -0
  144. package/lib/Utils/use-sqlite-auth-state.js +187 -0
  145. package/lib/Utils/vCard.d.ts +71 -0
  146. package/lib/Utils/vCard.js +196 -0
  147. package/lib/Utils/validate-connection.js +253 -0
  148. package/lib/Utils/warmup.js +154 -0
  149. package/lib/WABinary/constants.js +1303 -0
  150. package/lib/WABinary/decode.js +270 -0
  151. package/lib/WABinary/encode.js +279 -0
  152. package/lib/WABinary/generic-utils.js +223 -0
  153. package/lib/WABinary/index.js +34 -0
  154. package/lib/WABinary/jid-utils.js +84 -0
  155. package/lib/WABinary/types.js +2 -0
  156. package/lib/WAM/BinaryInfo.js +13 -0
  157. package/lib/WAM/constants.js +15254 -0
  158. package/lib/WAM/encode.js +149 -0
  159. package/lib/WAM/index.js +32 -0
  160. package/lib/WAUSync/Protocols/USyncContactProtocol.js +37 -0
  161. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +71 -0
  162. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +32 -0
  163. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +49 -0
  164. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +23 -0
  165. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +58 -0
  166. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  167. package/lib/WAUSync/Protocols/index.js +34 -0
  168. package/lib/WAUSync/USyncQuery.js +99 -0
  169. package/lib/WAUSync/USyncUser.js +26 -0
  170. package/lib/WAUSync/USyncUsernameProtocol.d.ts +9 -0
  171. package/lib/WAUSync/USyncUsernameProtocol.js +37 -0
  172. package/lib/WAUSync/index.js +32 -0
  173. package/lib/index.js +59 -0
  174. package/package.json +105 -5
  175. package/README.md +0 -5
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
@@ -0,0 +1,27 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.LabelColor = void 0
4
+ /** WhatsApp has 20 predefined colors */
5
+ var LabelColor
6
+ ;(function (LabelColor) {
7
+ LabelColor[(LabelColor['Color1'] = 0)] = 'Color1'
8
+ LabelColor[(LabelColor['Color2'] = 1)] = 'Color2'
9
+ LabelColor[(LabelColor['Color3'] = 2)] = 'Color3'
10
+ LabelColor[(LabelColor['Color4'] = 3)] = 'Color4'
11
+ LabelColor[(LabelColor['Color5'] = 4)] = 'Color5'
12
+ LabelColor[(LabelColor['Color6'] = 5)] = 'Color6'
13
+ LabelColor[(LabelColor['Color7'] = 6)] = 'Color7'
14
+ LabelColor[(LabelColor['Color8'] = 7)] = 'Color8'
15
+ LabelColor[(LabelColor['Color9'] = 8)] = 'Color9'
16
+ LabelColor[(LabelColor['Color10'] = 9)] = 'Color10'
17
+ LabelColor[(LabelColor['Color11'] = 10)] = 'Color11'
18
+ LabelColor[(LabelColor['Color12'] = 11)] = 'Color12'
19
+ LabelColor[(LabelColor['Color13'] = 12)] = 'Color13'
20
+ LabelColor[(LabelColor['Color14'] = 13)] = 'Color14'
21
+ LabelColor[(LabelColor['Color15'] = 14)] = 'Color15'
22
+ LabelColor[(LabelColor['Color16'] = 15)] = 'Color16'
23
+ LabelColor[(LabelColor['Color17'] = 16)] = 'Color17'
24
+ LabelColor[(LabelColor['Color18'] = 17)] = 'Color18'
25
+ LabelColor[(LabelColor['Color19'] = 18)] = 'Color19'
26
+ LabelColor[(LabelColor['Color20'] = 19)] = 'Color20'
27
+ })((LabelColor = exports.LabelColor || (exports.LabelColor = {})))
@@ -0,0 +1,9 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.LabelAssociationType = void 0
4
+ /** Association type */
5
+ var LabelAssociationType
6
+ ;(function (LabelAssociationType) {
7
+ LabelAssociationType['Chat'] = 'label_jid'
8
+ LabelAssociationType['Message'] = 'label_message'
9
+ })((LabelAssociationType = exports.LabelAssociationType || (exports.LabelAssociationType = {})))
@@ -0,0 +1,14 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.WAMessageStatus = exports.WAMessageStubType = exports.WAProto = void 0
4
+ const WAProto_1 = require('../../WAProto')
5
+ Object.defineProperty(exports, 'WAProto', {
6
+ enumerable: true,
7
+ get: function () {
8
+ return WAProto_1.proto
9
+ }
10
+ })
11
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
12
+ exports.WAMessageStubType = WAProto_1.proto.WebMessageInfo.StubType
13
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
14
+ exports.WAMessageStatus = WAProto_1.proto.WebMessageInfo.Status
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+
5
+ const MexUpdatesOperations = {
6
+ OWNER_COMMUNITY: 'NotificationCommunityOwnerUpdate',
7
+ GROUP_MEMBER_LINK: 'NotificationGroupMemberLinkPropertyUpdate',
8
+ GROUP_LIMIT_SHARING: 'NotificationGroupLimitSharingPropertyUpdate'
9
+ }
10
+
11
+ const XWAPathsMexUpdates = {
12
+ GROUP_SHARING_CHANGE: 'xwa2_notify_group_on_prop_change',
13
+ COMMUNITY_OWNER_CHANGE: 'xwa2_notify_group_on_participants_roles_change'
14
+ }
15
+
16
+ module.exports = {
17
+ MexUpdatesOperations,
18
+ XWAPathsMexUpdates
19
+ }
@@ -0,0 +1,38 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+
5
+ const MexOperations = {
6
+ PROMOTE: 'NotificationNewsletterAdminPromote',
7
+ DEMOTE: 'NotificationNewsletterAdminDemote',
8
+ UPDATE: 'NotificationNewsletterUpdate'
9
+ }
10
+
11
+ const XWAPaths = {
12
+ PROMOTE: 'xwa2_notify_newsletter_admin_promote',
13
+ DEMOTE: 'xwa2_notify_newsletter_admin_demote',
14
+ ADMIN_COUNT: 'xwa2_newsletter_admin',
15
+ CREATE: 'xwa2_newsletter_create',
16
+ NEWSLETTER: 'xwa2_newsletter',
17
+ SUBSCRIBED: 'xwa2_newsletter_subscribed',
18
+ METADATA_UPDATE: 'xwa2_notify_newsletter_on_metadata_update'
19
+ }
20
+
21
+ const QueryIds = {
22
+ JOB_MUTATION: '7150902998257522',
23
+ METADATA: '6620195908089573',
24
+ UNFOLLOW: '7238632346214362',
25
+ FOLLOW: '7871414976211147',
26
+ UNMUTE: '7337137176362961',
27
+ MUTE: '25151904754424642',
28
+ CREATE: '6996806640408138',
29
+ ADMIN_COUNT: '7130823597031706',
30
+ CHANGE_OWNER: '7341777602580933',
31
+ DELETE: '8316537688363079',
32
+ DEMOTE: '6551828931592903',
33
+ SUBSCRIBED: '6388546374527196'
34
+ }
35
+
36
+ exports.MexOperations = MexOperations
37
+ exports.XWAPaths = XWAPaths
38
+ exports.QueryIds = QueryIds
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
@@ -0,0 +1,30 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+
5
+ var CodeHighlightType
6
+ ;(function (CodeHighlightType) {
7
+ CodeHighlightType[(CodeHighlightType['DEFAULT'] = 0)] = 'DEFAULT'
8
+ CodeHighlightType[(CodeHighlightType['KEYWORD'] = 1)] = 'KEYWORD'
9
+ CodeHighlightType[(CodeHighlightType['METHOD'] = 2)] = 'METHOD'
10
+ CodeHighlightType[(CodeHighlightType['STRING'] = 3)] = 'STRING'
11
+ CodeHighlightType[(CodeHighlightType['NUMBER'] = 4)] = 'NUMBER'
12
+ CodeHighlightType[(CodeHighlightType['COMMENT'] = 5)] = 'COMMENT'
13
+ })(CodeHighlightType || (exports.CodeHighlightType = CodeHighlightType = {}))
14
+
15
+ var RichSubMessageType
16
+ ;(function (RichSubMessageType) {
17
+ RichSubMessageType[(RichSubMessageType['UNKNOWN'] = 0)] = 'UNKNOWN'
18
+ RichSubMessageType[(RichSubMessageType['GRID_IMAGE'] = 1)] = 'GRID_IMAGE'
19
+ RichSubMessageType[(RichSubMessageType['TEXT'] = 2)] = 'TEXT'
20
+ RichSubMessageType[(RichSubMessageType['INLINE_IMAGE'] = 3)] = 'INLINE_IMAGE'
21
+ RichSubMessageType[(RichSubMessageType['TABLE'] = 4)] = 'TABLE'
22
+ RichSubMessageType[(RichSubMessageType['CODE'] = 5)] = 'CODE'
23
+ RichSubMessageType[(RichSubMessageType['DYNAMIC'] = 6)] = 'DYNAMIC'
24
+ RichSubMessageType[(RichSubMessageType['MAP'] = 7)] = 'MAP'
25
+ RichSubMessageType[(RichSubMessageType['LATEX'] = 8)] = 'LATEX'
26
+ RichSubMessageType[(RichSubMessageType['CONTENT_ITEMS'] = 9)] = 'CONTENT_ITEMS'
27
+ })(RichSubMessageType || (exports.RichSubMessageType = RichSubMessageType = {}))
28
+
29
+ exports.CodeHighlightType = CodeHighlightType
30
+ exports.RichSubMessageType = RichSubMessageType
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
@@ -0,0 +1,58 @@
1
+ 'use strict'
2
+ var __createBinding =
3
+ (this && this.__createBinding) ||
4
+ (Object.create
5
+ ? function (o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k
7
+ var desc = Object.getOwnPropertyDescriptor(m, k)
8
+ if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = {
10
+ enumerable: true,
11
+ get: function () {
12
+ return m[k]
13
+ }
14
+ }
15
+ }
16
+ Object.defineProperty(o, k2, desc)
17
+ }
18
+ : function (o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k
20
+ o[k2] = m[k]
21
+ })
22
+ var __exportStar =
23
+ (this && this.__exportStar) ||
24
+ function (m, exports) {
25
+ for (var p in m)
26
+ if (p !== 'default' && !Object.prototype.hasOwnProperty.call(exports, p))
27
+ __createBinding(exports, m, p)
28
+ }
29
+ Object.defineProperty(exports, '__esModule', { value: true })
30
+ exports.DisconnectReason = void 0
31
+ __exportStar(require('./Auth'), exports)
32
+ __exportStar(require('./GroupMetadata'), exports)
33
+ __exportStar(require('./Chat'), exports)
34
+ __exportStar(require('./Contact'), exports)
35
+ __exportStar(require('./State'), exports)
36
+ __exportStar(require('./Message'), exports)
37
+ __exportStar(require('./Newsletter'), exports)
38
+ __exportStar(require('./Socket'), exports)
39
+ __exportStar(require('./Events'), exports)
40
+ __exportStar(require('./Product'), exports)
41
+ __exportStar(require('./Call'), exports)
42
+ __exportStar(require('./Signal'), exports)
43
+ var DisconnectReason
44
+ ;(function (DisconnectReason) {
45
+ DisconnectReason[(DisconnectReason['connectionClosed'] = 428)] = 'connectionClosed'
46
+ DisconnectReason[(DisconnectReason['connectionLost'] = 408)] = 'connectionLost'
47
+ DisconnectReason[(DisconnectReason['connectionReplaced'] = 440)] = 'connectionReplaced'
48
+ DisconnectReason[(DisconnectReason['timedOut'] = 408)] = 'timedOut'
49
+ DisconnectReason[(DisconnectReason['loggedOut'] = 401)] = 'loggedOut'
50
+ DisconnectReason[(DisconnectReason['badSession'] = 500)] = 'badSession'
51
+ DisconnectReason[(DisconnectReason['restartRequired'] = 515)] = 'restartRequired'
52
+ DisconnectReason[(DisconnectReason['multideviceMismatch'] = 411)] = 'multideviceMismatch'
53
+ DisconnectReason[(DisconnectReason['forbidden'] = 403)] = 'forbidden'
54
+ DisconnectReason[(DisconnectReason['unavailableService'] = 503)] = 'unavailableService'
55
+ })((DisconnectReason = exports.DisconnectReason || (exports.DisconnectReason = {})))
56
+
57
+ __exportStar(require('./MexUpdates'), exports)
58
+ __exportStar(require('./RichType'), exports)
@@ -0,0 +1,339 @@
1
+ "use strict"
2
+ Object.defineProperty(exports, "__esModule", { value: true })
3
+ exports.anti_ban = void 0
4
+
5
+ /**
6
+ * @file anti-ban.js
7
+ * @description Main orchestrator that wires together every anti-ban module
8
+ * (rate_limiter, warm_up, health_monitor, timelock_guard, reply_ratio_guard,
9
+ * contact_graph_warmer, presence_choreographer, retry_reason_tracker,
10
+ * post_reconnect_throttle, and optionally an external lid_resolver /
11
+ * jid_canonicalizer) into one simple call pattern:
12
+ *
13
+ * const ab = new anti_ban('moderate') // or 'conservative' / 'aggressive' / {preset, ...overrides}
14
+ * const decision = await ab.before_send(jid, text)
15
+ * if (!decision.allowed) return // skip / retry later
16
+ * if (decision.delayMs) await sleep(decision.delayMs)
17
+ * await sock.sendMessage(jid, { text })
18
+ * ab.after_send(jid, text)
19
+ *
20
+ * sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
21
+ * if (connection === 'close') ab.on_disconnect(lastDisconnect?.error?.output?.statusCode)
22
+ * if (connection === 'open') ab.on_reconnect()
23
+ * })
24
+ *
25
+ * @author Denzy ZeroDay
26
+ */
27
+
28
+ const { RateLimiter: rate_limiter } = require('./rate-limiter')
29
+ const { WarmUp: warm_up } = require('./warmup')
30
+ const { health_monitor } = require('./health-monitor')
31
+ const { timelock_guard } = require('./timelock-guard')
32
+ const { reply_ratio_guard } = require('./reply-ratio-guard')
33
+ const { contact_graph_warmer } = require('./contact-graph-warmer')
34
+ const { presence_choreographer } = require('./presence-choreographer')
35
+ const { retry_reason_tracker } = require('./retry-reason-tracker')
36
+ const { PostReconnectThrottle: post_reconnect_throttle } = require('./reconnect-throttle')
37
+ const { resolve_antiban_config } = require('./antiban-presets')
38
+ const { should_use_group_profile, apply_group_multiplier } = require('./antiban-profiles')
39
+ const { state_manager } = require('./state-manager')
40
+
41
+ class anti_ban {
42
+ /**
43
+ * @param {string|object} input - preset name ('conservative'|'moderate'|'aggressive'), or { preset, ...overrides }, or nothing
44
+ * @param {object} warm_up_state - optional restored warmup state (skip if using config.persist)
45
+ */
46
+ constructor(input, warm_up_state) {
47
+ const cfg = resolve_antiban_config(input)
48
+ this.resolved_config = cfg
49
+ this.state_manager_instance = null
50
+
51
+ let saved_state = null
52
+ if (cfg.persist) {
53
+ this.state_manager_instance = new state_manager(cfg.persist)
54
+ saved_state = this.state_manager_instance.load()
55
+ if (saved_state) warm_up_state = saved_state.warmup
56
+ }
57
+
58
+ this.logging = cfg.logging ?? true
59
+ this._log = (msg) => { if (this.logging) process.stdout.write(`[anti_ban] ${msg}\n`) }
60
+
61
+ this.rate_limiter = new rate_limiter({
62
+ maxPerMinute: cfg.maxPerMinute,
63
+ maxPerHour: cfg.maxPerHour,
64
+ maxPerDay: cfg.maxPerDay,
65
+ minDelayMs: cfg.minDelayMs,
66
+ maxDelayMs: cfg.maxDelayMs,
67
+ newChatDelayMs: cfg.newChatDelayMs
68
+ })
69
+ if (saved_state?.knownChats) this.rate_limiter.restoreKnownChats(saved_state.knownChats)
70
+
71
+ this.warm_up = new warm_up({
72
+ warmUpDays: cfg.warmupDays,
73
+ day1Limit: cfg.day1Limit,
74
+ growthFactor: cfg.growthFactor,
75
+ inactivityThresholdHours: cfg.inactivityThresholdHours
76
+ }, warm_up_state)
77
+
78
+ this.health = new health_monitor({
79
+ auto_pause_at: cfg.autoPauseAt,
80
+ onRiskChange: (status) => {
81
+ const emoji = { low: '🟢', medium: '🟡', high: '🟠', critical: '🔴' }
82
+ this._log(`${emoji[status.risk]} Risk level: ${status.risk.toUpperCase()} (score: ${status.score})`)
83
+ this._log(status.recommendation)
84
+ status.reasons.forEach(r => this._log(` → ${r}`))
85
+ }
86
+ })
87
+
88
+ this.timelock_guard = new timelock_guard({
89
+ onTimelockDetected: (state) => {
90
+ this.health.record_reachout_timelock(state.enforcement_type)
91
+ this._log(`REACHOUT TIMELOCKED — ${state.enforcement_type || 'unknown'}, expires ${state.expires_at?.toISOString?.() || 'unknown'}`)
92
+ },
93
+ onTimelockLifted: () => {
94
+ this._log('Timelock lifted — resuming new contact messages')
95
+ }
96
+ })
97
+
98
+ this.reply_ratio_guard = new reply_ratio_guard()
99
+ this.contact_graph_warmer = new contact_graph_warmer()
100
+ this.presence_choreographer = new presence_choreographer()
101
+ this.retry_reason_tracker = new retry_reason_tracker({
102
+ onSpiral: (msg_id, reason) => {
103
+ this._log(`⚠️ Message ${msg_id} stuck in retry spiral (${reason})`)
104
+ }
105
+ })
106
+ this.reconnect_throttle = new post_reconnect_throttle({
107
+ baselineRatePerMinute: () => this.rate_limiter.getStats().limits.perMinute
108
+ })
109
+
110
+ // Optional external LID support — pass config.lid_resolver / config.jid_canonicalizer yourself.
111
+ // These are not bundled here (see tahap 2 / LID support), but anti_ban will use them if provided.
112
+ this.lid_resolver = null
113
+ this.jid_canonicalizer = null
114
+ this.session_stability_monitor = null
115
+
116
+ this.stats = { messagesAllowed: 0, messagesBlocked: 0, totalDelayMs: 0 }
117
+ }
118
+
119
+ /**
120
+ * Check if a message can be sent and compute the required human-like delay.
121
+ * Call this BEFORE every sock.sendMessage().
122
+ * @returns {{ allowed: boolean, delayMs: number, reason?: string, health: object, warmUpDay?: number }}
123
+ */
124
+ async before_send(recipient, content) {
125
+ const health_status = this.health.get_status()
126
+
127
+ if (this.health.is_paused()) {
128
+ this.stats.messagesBlocked++
129
+ this._log(`⛔ BLOCKED — health risk too high (${health_status.risk})`)
130
+ return { allowed: false, delayMs: 0, reason: `Health risk ${health_status.risk}: ${health_status.recommendation}`, health: health_status }
131
+ }
132
+
133
+ const timelock_decision = this.timelock_guard.can_send(recipient)
134
+ if (!timelock_decision.allowed) {
135
+ this.stats.messagesBlocked++
136
+ this._log(`TIMELOCKED — ${timelock_decision.reason}`)
137
+ return { allowed: false, delayMs: 0, reason: timelock_decision.reason, health: health_status }
138
+ }
139
+
140
+ if (!this.warm_up.canSend()) {
141
+ this.stats.messagesBlocked++
142
+ const warm_up_status = this.warm_up.getStatus()
143
+ this._log(`⏳ BLOCKED — warm-up day ${warm_up_status.day}/${warm_up_status.totalDays}, limit reached (${warm_up_status.todaySent}/${warm_up_status.todayLimit})`)
144
+ return {
145
+ allowed: false, delayMs: 0,
146
+ reason: `Warm-up limit: ${warm_up_status.todaySent}/${warm_up_status.todayLimit} messages today (day ${warm_up_status.day})`,
147
+ health: health_status, warmUpDay: warm_up_status.day
148
+ }
149
+ }
150
+
151
+ const contact_graph_decision = this.contact_graph_warmer.can_message(recipient)
152
+ if (!contact_graph_decision.allowed) {
153
+ this.stats.messagesBlocked++
154
+ this._log(`📊 BLOCKED — contact graph: ${contact_graph_decision.reason}`)
155
+ return { allowed: false, delayMs: 0, reason: `Contact graph: ${contact_graph_decision.reason}`, health: health_status }
156
+ }
157
+
158
+ const reply_ratio_decision = this.reply_ratio_guard.before_send(recipient)
159
+ if (!reply_ratio_decision.allowed) {
160
+ this.stats.messagesBlocked++
161
+ this._log(`💬 BLOCKED — reply ratio: ${reply_ratio_decision.reason}`)
162
+ return { allowed: false, delayMs: 0, reason: `Reply ratio: ${reply_ratio_decision.reason}`, health: health_status }
163
+ }
164
+
165
+ const reconnect_decision = this.reconnect_throttle.beforeSend()
166
+ if (!reconnect_decision.allowed) {
167
+ this.stats.messagesBlocked++
168
+ this._log(`🔄 BLOCKED — reconnect throttle: ${reconnect_decision.reason}`)
169
+ return { allowed: false, delayMs: reconnect_decision.retryAfterMs || 0, reason: reconnect_decision.reason || 'Post-reconnect throttle', health: health_status }
170
+ }
171
+
172
+ if (this.resolved_config.groupProfiles && should_use_group_profile(recipient)) {
173
+ const group_limits = apply_group_multiplier(
174
+ { maxPerMinute: this.resolved_config.maxPerMinute, maxPerHour: this.resolved_config.maxPerHour, maxPerDay: this.resolved_config.maxPerDay },
175
+ this.resolved_config.groupMultiplier
176
+ )
177
+ const stats = this.rate_limiter.getStats()
178
+ if (stats.lastMinute >= group_limits.maxPerMinute || stats.lastHour >= group_limits.maxPerHour || stats.lastDay >= group_limits.maxPerDay) {
179
+ this.stats.messagesBlocked++
180
+ this._log(`🚫 BLOCKED — group rate limit exceeded for ${recipient}`)
181
+ return { allowed: false, delayMs: 0, reason: 'Group rate limit exceeded', health: health_status }
182
+ }
183
+ }
184
+
185
+ let delay = await this.rate_limiter.getDelay(recipient, content)
186
+ if (delay === -1) {
187
+ this.stats.messagesBlocked++
188
+ this._log('🚫 BLOCKED — rate limit or identical message spam')
189
+ return { allowed: false, delayMs: 0, reason: 'Rate limit exceeded or identical message spam detected', health: health_status }
190
+ }
191
+
192
+ const activity_factor = this.presence_choreographer.get_current_activity_factor()
193
+ if (activity_factor < 1) {
194
+ const multiplier = Math.min(5, 1 / activity_factor)
195
+ delay = Math.floor(delay * multiplier)
196
+ }
197
+
198
+ const distraction_check = this.presence_choreographer.should_pause_for_distraction()
199
+ if (distraction_check.pause) {
200
+ delay += distraction_check.duration_ms
201
+ this._log(`⏸️ Distraction pause: +${Math.floor(distraction_check.duration_ms / 60000)}min`)
202
+ }
203
+
204
+ const offline_check = this.presence_choreographer.should_take_offline_gap()
205
+ if (offline_check.offline) {
206
+ delay += offline_check.duration_ms
207
+ this._log(`📴 Offline gap: +${Math.floor(offline_check.duration_ms / 60000)}min`)
208
+ }
209
+
210
+ this.stats.totalDelayMs += delay
211
+ return { allowed: true, delayMs: delay, health: health_status }
212
+ }
213
+
214
+ /** Record a successfully sent message. Call this AFTER every successful sendMessage(). */
215
+ after_send(recipient, content) {
216
+ this.rate_limiter.record(recipient, content)
217
+ this.warm_up.record()
218
+ this.reply_ratio_guard.record_sent(recipient)
219
+ this.stats.messagesAllowed++
220
+ this.persist_state_debounced()
221
+ }
222
+
223
+ /** Record a failed message send */
224
+ after_send_failed(error) {
225
+ this.health.record_message_failed(error)
226
+ }
227
+
228
+ /** Record a disconnection (call from connection.update handler) */
229
+ on_disconnect(reason) {
230
+ this.health.record_disconnect(reason)
231
+ this.reconnect_throttle.onDisconnect()
232
+ const reason_str = String(reason)
233
+ if (reason_str === '403' || reason_str === '401' || reason_str === 'forbidden' || reason_str === 'loggedOut') {
234
+ this.persist_state_immediate()
235
+ }
236
+ }
237
+
238
+ /** Record a successful reconnection */
239
+ on_reconnect() {
240
+ this.health.record_reconnect()
241
+ this.reconnect_throttle.onReconnect()
242
+ }
243
+
244
+ /**
245
+ * Handle incoming message — records in reply ratio + contact graph.
246
+ * Returns suggested reply if reply ratio suggests an auto-reply.
247
+ */
248
+ on_incoming_message(jid, msg_text) {
249
+ this.reply_ratio_guard.record_received(jid)
250
+ this.contact_graph_warmer.on_incoming_message(jid)
251
+ return this.reply_ratio_guard.suggest_reply(jid, msg_text)
252
+ }
253
+
254
+ /** Get comprehensive stats across all enabled modules */
255
+ get_stats() {
256
+ const stats = {
257
+ ...this.stats,
258
+ health: this.health.get_status(),
259
+ warmUp: this.warm_up.getStatus(),
260
+ rateLimiter: this.rate_limiter.getStats()
261
+ }
262
+ if (this.reply_ratio_guard.config?.enabled) stats.replyRatio = this.reply_ratio_guard.get_stats()
263
+ if (this.contact_graph_warmer.config?.enabled) stats.contactGraph = this.contact_graph_warmer.get_stats()
264
+ if (this.presence_choreographer.config?.enabled) stats.presence = this.presence_choreographer.get_stats()
265
+ if (this.retry_reason_tracker.config?.enabled) stats.retryTracker = this.retry_reason_tracker.get_stats()
266
+ if (this.reconnect_throttle.config?.enabled) stats.reconnectThrottle = this.reconnect_throttle.getStats()
267
+ if (this.lid_resolver) stats.lidResolver = this.lid_resolver.getStats?.()
268
+ if (this.jid_canonicalizer) stats.jidCanonicalizer = this.jid_canonicalizer.getStats?.()
269
+ if (this.session_stability_monitor) stats.sessionStability = this.session_stability_monitor.get_stats()
270
+ return stats
271
+ }
272
+
273
+ /** Force pause all sending */
274
+ pause() {
275
+ this.health.set_paused(true)
276
+ this._log('⏸️ Sending paused manually')
277
+ }
278
+
279
+ /** Resume sending */
280
+ resume() {
281
+ this.health.set_paused(false)
282
+ this._log('▶️ Sending resumed')
283
+ }
284
+
285
+ /** Reset everything (use after a ban period) */
286
+ reset() {
287
+ this.timelock_guard.reset()
288
+ this.health.reset()
289
+ this.warm_up.reset()
290
+ this.reply_ratio_guard.reset()
291
+ this.contact_graph_warmer.reset()
292
+ this.presence_choreographer.reset()
293
+ this.retry_reason_tracker.destroy()
294
+ this.reconnect_throttle.destroy()
295
+ this.stats = { messagesAllowed: 0, messagesBlocked: 0, totalDelayMs: 0 }
296
+ this._log('🔄 Reset — starting fresh warm-up')
297
+ }
298
+
299
+ /** Export warm-up state for persistence between restarts */
300
+ export_warmup_state() {
301
+ return this.warm_up.exportState()
302
+ }
303
+
304
+ persist_state_debounced() {
305
+ if (!this.state_manager_instance) return
306
+ this.state_manager_instance.save_debounced({
307
+ warmup: this.warm_up.exportState(),
308
+ knownChats: Array.from(this.rate_limiter.getKnownChats()),
309
+ savedAt: Date.now(),
310
+ version: 3
311
+ })
312
+ }
313
+
314
+ persist_state_immediate() {
315
+ if (!this.state_manager_instance) return
316
+ this.state_manager_instance.save_immediate({
317
+ warmup: this.warm_up.exportState(),
318
+ knownChats: Array.from(this.rate_limiter.getKnownChats()),
319
+ savedAt: Date.now(),
320
+ version: 3
321
+ })
322
+ }
323
+
324
+ /** Clean up all timers and resources. Call when disposing the instance or when the socket closes. */
325
+ destroy() {
326
+ this.state_manager_instance?.destroy()
327
+ this.timelock_guard.reset()
328
+ this.reply_ratio_guard.reset()
329
+ this.contact_graph_warmer.reset()
330
+ this.presence_choreographer.reset()
331
+ this.retry_reason_tracker.destroy()
332
+ this.reconnect_throttle.destroy()
333
+ this.session_stability_monitor?.reset()
334
+ this._log('🧹 Destroyed — all timers cleared')
335
+ }
336
+ }
337
+
338
+ exports.anti_ban = anti_ban
339
+ module.exports = { anti_ban }