@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,147 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.GroupOperationGuard =
4
+ exports.extractPrivacyBlock =
5
+ exports.classifyGroupOpError =
6
+ exports.GROUP_OP_ERRORS =
7
+ void 0
8
+
9
+ /**
10
+ * @file group-operation-guard.js
11
+ * @description Rate limiting for WhatsApp group operations.
12
+ * Prevents account_reachout_restricted and rate-overlimit errors
13
+ * by enforcing per-operation windows on group adds, removes, and creates.
14
+ *
15
+ * WA unofficial limits (observed):
16
+ * - groupParticipantsUpdate (add): ~3 new contacts per 10 min
17
+ * - groupCreate: ~2 per 10 min
18
+ * - Rapid retries after 403: triggers account_reachout_restricted
19
+ *
20
+ * Ported from baileys-antiban to CJS for bilis.
21
+ * @author Denzy ZeroDay (port), original by baileys-antiban contributors
22
+ */
23
+
24
+ const DEFAULT_LIMITS = {
25
+ add: { max: 3, windowMs: 10 * 60 * 1000 }, // 3 adds / 10 min
26
+ remove: { max: 5, windowMs: 10 * 60 * 1000 }, // 5 removes / 10 min
27
+ create: { max: 2, windowMs: 10 * 60 * 1000 }, // 2 creates / 10 min
28
+ invite: { max: 10, windowMs: 10 * 60 * 1000 } // 10 invite fetches / 10 min
29
+ }
30
+
31
+ /** Known WA error patterns for group operations */
32
+ const GROUP_OP_ERRORS = {
33
+ REACHOUT_RESTRICTED: 'account_reachout_restricted',
34
+ RATE_OVERLIMIT: 'rate-overlimit',
35
+ PRIVACY_BLOCK: '403',
36
+ INVITE_EXPIRED: 'gone',
37
+ GROUP_LOCKED: 'locked'
38
+ }
39
+ exports.GROUP_OP_ERRORS = GROUP_OP_ERRORS
40
+
41
+ /**
42
+ * Classify a caught error from a group operation.
43
+ * @param {unknown} err
44
+ * @returns {string|null}
45
+ */
46
+ const classifyGroupOpError = (err) => {
47
+ const msg = err instanceof Error ? err.message : String(err)
48
+ if (msg.includes('account_reachout_restricted') || msg.includes('reachout'))
49
+ return GROUP_OP_ERRORS.REACHOUT_RESTRICTED
50
+ if (msg.includes('rate-overlimit') || msg.includes('429')) return GROUP_OP_ERRORS.RATE_OVERLIMIT
51
+ if (msg.includes('locked')) return GROUP_OP_ERRORS.GROUP_LOCKED
52
+ if (msg.includes('gone')) return GROUP_OP_ERRORS.INVITE_EXPIRED
53
+ return null
54
+ }
55
+ exports.classifyGroupOpError = classifyGroupOpError
56
+
57
+ /**
58
+ * Check whether a groupParticipantsUpdate result contains a privacy-block 403
59
+ * with an invite code that should be used instead of direct add.
60
+ * @param {Array} result - Result from sock.groupParticipantsUpdate()
61
+ * @returns {{ blocked: boolean, inviteCode?: string, inviteLink?: string }}
62
+ */
63
+ const extractPrivacyBlock = (result) => {
64
+ if (!Array.isArray(result)) return { blocked: false }
65
+ for (const r of result) {
66
+ if (r.status !== '403') continue
67
+ const content = Array.isArray(r.content) ? r.content : []
68
+ for (const c of content) {
69
+ if (c.tag === 'add_request' && typeof c.attrs === 'object' && c.attrs.code) {
70
+ return {
71
+ blocked: true,
72
+ inviteCode: c.attrs.code,
73
+ inviteLink: `https://chat.whatsapp.com/${c.attrs.code}`
74
+ }
75
+ }
76
+ }
77
+ return { blocked: true }
78
+ }
79
+ return { blocked: false }
80
+ }
81
+ exports.extractPrivacyBlock = extractPrivacyBlock
82
+
83
+ class GroupOperationGuard {
84
+ /**
85
+ * @param {object} config
86
+ * @param {object} config.limits - Override per-operation limits
87
+ */
88
+ constructor(config = {}) {
89
+ this.limits = { ...DEFAULT_LIMITS, ...(config.limits || {}) }
90
+ this.windows = new Map()
91
+ }
92
+
93
+ /**
94
+ * Check whether an operation is allowed under the current rate limits.
95
+ * @param {'add'|'remove'|'create'|'invite'} op - Operation type
96
+ * @param {string} key - Unique key scoping the limit (e.g. groupJid)
97
+ * @returns {{ allowed: boolean, reason?: string, retryAfterSec?: number }}
98
+ */
99
+ check(op, key) {
100
+ const limit = this.limits[op]
101
+ if (!limit) return { allowed: true }
102
+ const windowKey = `${op}:${key}`
103
+ const now = Date.now()
104
+ const entry = this.windows.get(windowKey)
105
+
106
+ if (!entry || now > entry.resetAt) {
107
+ this.windows.set(windowKey, { count: 1, resetAt: now + limit.windowMs })
108
+ return { allowed: true }
109
+ }
110
+
111
+ if (entry.count >= limit.max) {
112
+ const retryAfterSec = Math.ceil((entry.resetAt - now) / 1000)
113
+ return {
114
+ allowed: false,
115
+ reason: `Too many ${op} attempts — wait ${Math.ceil(retryAfterSec / 60)} min before trying again.`,
116
+ retryAfterSec
117
+ }
118
+ }
119
+
120
+ entry.count++
121
+ return { allowed: true }
122
+ }
123
+
124
+ /**
125
+ * Reset the counter for a specific operation + key.
126
+ * @param {'add'|'remove'|'create'|'invite'} op
127
+ * @param {string} key
128
+ */
129
+ reset(op, key) {
130
+ this.windows.delete(`${op}:${key}`)
131
+ }
132
+
133
+ /**
134
+ * Snapshot of all active windows.
135
+ * @returns {object}
136
+ */
137
+ getStats() {
138
+ const stats = {}
139
+ for (const [key, val] of this.windows) {
140
+ stats[key] = { ...val }
141
+ }
142
+ return stats
143
+ }
144
+ }
145
+
146
+ exports.GroupOperationGuard = GroupOperationGuard
147
+ module.exports = { GroupOperationGuard, classifyGroupOpError, extractPrivacyBlock, GROUP_OP_ERRORS }
@@ -0,0 +1,207 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.health_monitor = void 0
4
+
5
+ /**
6
+ * @file health-monitor.js
7
+ * @description Tracks disconnects, forbidden errors, logouts, and failed
8
+ * messages to compute a ban-risk score with actionable recommendations.
9
+ * @author Denzy ZeroDay
10
+ */
11
+
12
+ const default_config = {
13
+ disconnect_warning_threshold: 3,
14
+ disconnect_critical_threshold: 5,
15
+ failed_message_threshold: 5,
16
+ auto_pause_at: 'high'
17
+ }
18
+
19
+ class health_monitor {
20
+ constructor(config = {}) {
21
+ this.config = { ...default_config, ...config }
22
+ this.events = []
23
+ this.start_time = Date.now()
24
+ this.paused = false
25
+ this.last_risk = 'low'
26
+ this.last_bad_event_time = Date.now()
27
+ this.last_event_was_severe = false
28
+ }
29
+
30
+ /** Record a disconnection event */
31
+ record_disconnect(reason) {
32
+ const reason_str = String(reason)
33
+ if (reason_str === '403' || reason_str === 'forbidden') {
34
+ this.events.push({ type: 'forbidden', timestamp: Date.now(), detail: reason_str })
35
+ this.last_bad_event_time = Date.now()
36
+ this.last_event_was_severe = true
37
+ } else if (reason_str === '401' || reason_str === 'loggedOut') {
38
+ this.events.push({ type: 'loggedOut', timestamp: Date.now(), detail: reason_str })
39
+ this.last_bad_event_time = Date.now()
40
+ this.last_event_was_severe = true
41
+ } else if (reason_str === '463') {
42
+ this.events.push({
43
+ type: 'reachoutTimelocked',
44
+ timestamp: Date.now(),
45
+ detail: reason_str
46
+ })
47
+ this.last_bad_event_time = Date.now()
48
+ this.last_event_was_severe = false
49
+ } else {
50
+ this.events.push({ type: 'disconnect', timestamp: Date.now(), detail: reason_str })
51
+ this.last_bad_event_time = Date.now()
52
+ this.last_event_was_severe = false
53
+ }
54
+ this._check_and_notify()
55
+ }
56
+
57
+ /** Record a successful reconnection */
58
+ record_reconnect() {
59
+ this.events.push({ type: 'reconnect', timestamp: Date.now() })
60
+ }
61
+
62
+ /** Record a failed message send */
63
+ record_message_failed(error) {
64
+ this.events.push({ type: 'messageFailed', timestamp: Date.now(), detail: error })
65
+ this.last_bad_event_time = Date.now()
66
+ this.last_event_was_severe = false
67
+ this._check_and_notify()
68
+ }
69
+
70
+ /** Record a 463 reachout timelock error */
71
+ record_reachout_timelock(detail) {
72
+ this.events.push({ type: 'reachoutTimelocked', timestamp: Date.now(), detail })
73
+ this.last_bad_event_time = Date.now()
74
+ this.last_event_was_severe = false
75
+ this._check_and_notify()
76
+ }
77
+
78
+ /** Get current health status with ban-risk score and recommendation */
79
+ get_status() {
80
+ const now = Date.now()
81
+ this._cleanup(now)
82
+
83
+ const hour_events = this.events.filter((e) => now - e.timestamp < 3600000)
84
+ const disconnects = hour_events.filter((e) => e.type === 'disconnect').length
85
+ const forbidden = hour_events.filter((e) => e.type === 'forbidden').length
86
+ const logged_out = hour_events.filter((e) => e.type === 'loggedOut').length
87
+ const failed_messages = hour_events.filter((e) => e.type === 'messageFailed').length
88
+ const timelocked = hour_events.filter((e) => e.type === 'reachoutTimelocked').length
89
+
90
+ let score = 0
91
+ const reasons = []
92
+
93
+ if (forbidden > 0) {
94
+ score += 40 * forbidden
95
+ reasons.push(
96
+ `${forbidden} forbidden (403) error${forbidden > 1 ? 's' : ''} in last hour`
97
+ )
98
+ }
99
+ if (logged_out > 0) {
100
+ score += 60
101
+ reasons.push('Logged out by WhatsApp — possible temporary ban')
102
+ }
103
+ if (timelocked > 0) {
104
+ score += 25
105
+ reasons.push(
106
+ `${timelocked} reachout timelock (463) error${timelocked > 1 ? 's' : ''} in last hour`
107
+ )
108
+ }
109
+ if (disconnects >= this.config.disconnect_critical_threshold) {
110
+ score += 30
111
+ reasons.push(`${disconnects} disconnects in last hour (critical threshold)`)
112
+ } else if (disconnects >= this.config.disconnect_warning_threshold) {
113
+ score += 30
114
+ reasons.push(`${disconnects} disconnects in last hour`)
115
+ }
116
+ if (failed_messages >= this.config.failed_message_threshold) {
117
+ score += 20
118
+ reasons.push(`${failed_messages} failed messages in last hour`)
119
+ }
120
+
121
+ score = Math.min(100, score)
122
+ const minutes_since_last_bad = (now - this.last_bad_event_time) / 60000
123
+ const decay_rate = this.last_event_was_severe ? 2 : 5
124
+ score = Math.max(0, score - Math.floor(minutes_since_last_bad * decay_rate))
125
+
126
+ let risk
127
+ if (score >= 80) risk = 'critical'
128
+ else if (score >= 40) risk = 'high'
129
+ else if (score >= 15) risk = 'medium'
130
+ else risk = 'low'
131
+
132
+ let recommendation
133
+ switch (risk) {
134
+ case 'critical':
135
+ recommendation =
136
+ 'STOP ALL MESSAGING IMMEDIATELY. Disconnect and wait 24-48 hours before reconnecting.'
137
+ break
138
+ case 'high':
139
+ recommendation = 'Reduce messaging rate by 80%. Consider pausing for 1-2 hours.'
140
+ break
141
+ case 'medium':
142
+ recommendation = 'Reduce messaging rate by 50%. Increase delays between messages.'
143
+ break
144
+ default:
145
+ recommendation = 'Operating normally. Continue monitoring.'
146
+ }
147
+
148
+ const last_disconnect = [...this.events]
149
+ .reverse()
150
+ .find(
151
+ (e) => e.type === 'disconnect' || e.type === 'forbidden' || e.type === 'loggedOut'
152
+ )
153
+
154
+ return {
155
+ risk,
156
+ score,
157
+ reasons: reasons.length ? reasons : ['No issues detected'],
158
+ recommendation,
159
+ stats: {
160
+ disconnectsLastHour: disconnects,
161
+ failedMessagesLastHour: failed_messages,
162
+ forbiddenErrors: forbidden,
163
+ timelockErrors: timelocked,
164
+ uptimeMs: now - this.start_time,
165
+ lastDisconnectReason: last_disconnect?.detail
166
+ }
167
+ }
168
+ }
169
+
170
+ /** Check if sending should be paused based on current risk */
171
+ is_paused() {
172
+ if (this.paused) return true
173
+ const status = this.get_status()
174
+ const risk_order = ['low', 'medium', 'high', 'critical']
175
+ return risk_order.indexOf(status.risk) >= risk_order.indexOf(this.config.auto_pause_at)
176
+ }
177
+
178
+ /** Manually pause/resume sending */
179
+ set_paused(paused) {
180
+ this.paused = paused
181
+ }
182
+
183
+ /** Reset all tracked events */
184
+ reset() {
185
+ this.events = []
186
+ this.start_time = Date.now()
187
+ this.paused = false
188
+ this.last_risk = 'low'
189
+ this.last_bad_event_time = Date.now()
190
+ this.last_event_was_severe = false
191
+ }
192
+
193
+ _cleanup(now) {
194
+ this.events = this.events.filter((e) => now - e.timestamp < 21600000)
195
+ }
196
+
197
+ _check_and_notify() {
198
+ const status = this.get_status()
199
+ if (status.risk !== this.last_risk) {
200
+ this.last_risk = status.risk
201
+ this.config.onRiskChange?.(status)
202
+ }
203
+ }
204
+ }
205
+
206
+ exports.health_monitor = health_monitor
207
+ module.exports = { health_monitor }
@@ -0,0 +1,122 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.getHistoryMsg =
4
+ exports.downloadAndProcessHistorySyncNotification =
5
+ exports.processHistoryMessage =
6
+ exports.downloadHistory =
7
+ void 0
8
+ const util_1 = require('util')
9
+ const zlib_1 = require('zlib')
10
+ const WAProto_1 = require('../../WAProto')
11
+ const Types_1 = require('../Types')
12
+ const WABinary_1 = require('../WABinary')
13
+ const generics_1 = require('./generics')
14
+ const messages_1 = require('./messages')
15
+ const messages_media_1 = require('./messages-media')
16
+ const inflatePromise = (0, util_1.promisify)(zlib_1.inflate)
17
+ const downloadHistory = async (msg, options) => {
18
+ const stream = await (0, messages_media_1.downloadContentFromMessage)(msg, 'md-msg-hist', {
19
+ options
20
+ })
21
+ const bufferArray = []
22
+ for await (const chunk of stream) {
23
+ bufferArray.push(chunk)
24
+ }
25
+ let buffer = Buffer.concat(bufferArray)
26
+ // decompress buffer
27
+ buffer = await inflatePromise(buffer)
28
+ const syncData = WAProto_1.proto.HistorySync.decode(buffer)
29
+ return syncData
30
+ }
31
+ exports.downloadHistory = downloadHistory
32
+ const processHistoryMessage = (item) => {
33
+ var _a, _b, _c
34
+ const messages = []
35
+ const contacts = []
36
+ const chats = []
37
+ switch (item.syncType) {
38
+ case WAProto_1.proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP:
39
+ case WAProto_1.proto.HistorySync.HistorySyncType.RECENT:
40
+ case WAProto_1.proto.HistorySync.HistorySyncType.FULL:
41
+ case WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND:
42
+ for (const chat of item.conversations) {
43
+ contacts.push({
44
+ id: chat.id,
45
+ name: chat.name || undefined,
46
+ lid: chat.lidJid || undefined,
47
+ jid: (0, WABinary_1.isJidUser)(chat.id) ? chat.id : undefined
48
+ })
49
+ const msgs = chat.messages || []
50
+ delete chat.messages
51
+ delete chat.archived
52
+ delete chat.muteEndTime
53
+ delete chat.pinned
54
+ for (const item of msgs) {
55
+ const message = item.message
56
+ messages.push(message)
57
+ if (!((_a = chat.messages) === null || _a === void 0 ? void 0 : _a.length)) {
58
+ // keep only the most recent message in the chat array
59
+ chat.messages = [{ message }]
60
+ }
61
+ if (!message.key.fromMe && !chat.lastMessageRecvTimestamp) {
62
+ chat.lastMessageRecvTimestamp = (0, generics_1.toNumber)(
63
+ message.messageTimestamp
64
+ )
65
+ }
66
+ if (
67
+ (message.messageStubType ===
68
+ Types_1.WAMessageStubType.BIZ_PRIVACY_MODE_TO_BSP ||
69
+ message.messageStubType ===
70
+ Types_1.WAMessageStubType.BIZ_PRIVACY_MODE_TO_FB) &&
71
+ ((_b = message.messageStubParameters) === null || _b === void 0
72
+ ? void 0
73
+ : _b[0])
74
+ ) {
75
+ contacts.push({
76
+ id: message.key.participant || message.key.remoteJid,
77
+ verifiedName:
78
+ (_c = message.messageStubParameters) === null || _c === void 0
79
+ ? void 0
80
+ : _c[0]
81
+ })
82
+ }
83
+ }
84
+ if ((0, WABinary_1.isJidUser)(chat.id) && chat.readOnly && chat.archived) {
85
+ delete chat.readOnly
86
+ }
87
+ chats.push({ ...chat })
88
+ }
89
+ break
90
+ case WAProto_1.proto.HistorySync.HistorySyncType.PUSH_NAME:
91
+ for (const c of item.pushnames) {
92
+ contacts.push({ id: c.id, notify: c.pushname })
93
+ }
94
+ break
95
+ }
96
+ return {
97
+ chats,
98
+ contacts,
99
+ messages
100
+ }
101
+ }
102
+ exports.processHistoryMessage = processHistoryMessage
103
+ const downloadAndProcessHistorySyncNotification = async (msg, options) => {
104
+ const historyMsg = await (0, exports.downloadHistory)(msg, options)
105
+ return (0, exports.processHistoryMessage)(historyMsg)
106
+ }
107
+ exports.downloadAndProcessHistorySyncNotification = downloadAndProcessHistorySyncNotification
108
+ const getHistoryMsg = (message) => {
109
+ var _a
110
+ const normalizedContent = !!message
111
+ ? (0, messages_1.normalizeMessageContent)(message)
112
+ : undefined
113
+ const anyHistoryMsg =
114
+ (_a =
115
+ normalizedContent === null || normalizedContent === void 0
116
+ ? void 0
117
+ : normalizedContent.protocolMessage) === null || _a === void 0
118
+ ? void 0
119
+ : _a.historySyncNotification
120
+ return anyHistoryMsg
121
+ }
122
+ exports.getHistoryMsg = getHistoryMsg
@@ -0,0 +1,226 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.HumanEntropyService = exports.createHumanEntropyService = void 0
4
+
5
+ /**
6
+ * @file human-entropy.js
7
+ * @description Background noise for WA sessions — fake human activity
8
+ * to prevent bot detection. Performs random typing presence, delayed
9
+ * read receipts, and availability status toggles periodically.
10
+ * Ported from baileys-antiban to CJS for bilis.
11
+ * @author Denzy ZeroDay (port), original by baileys-antiban contributors
12
+ */
13
+
14
+ const DEFAULT_CONFIG = {
15
+ enabled: true,
16
+ minIntervalMs: 2 * 60 * 60 * 1000, // 2 hours
17
+ maxIntervalMs: 6 * 60 * 60 * 1000, // 6 hours
18
+ maxRecentContacts: 30,
19
+ typingProbability: 0.3,
20
+ typingMinMs: 3000,
21
+ typingMaxMs: 8000,
22
+ readReceiptProbability: 0.2,
23
+ readReceiptMinDelayMs: 10 * 60 * 1000, // 10 min
24
+ readReceiptMaxDelayMs: 60 * 60 * 1000, // 60 min
25
+ presenceToggleProbability: 0.15,
26
+ presenceToggleMinMs: 30 * 1000, // 30 sec
27
+ presenceToggleMaxMs: 2 * 60 * 1000 // 2 min
28
+ }
29
+
30
+ class HumanEntropyService {
31
+ /**
32
+ * @param {object} sock - Baileys WASocket instance
33
+ * @param {object} config - Optional config overrides
34
+ */
35
+ constructor(sock, config = {}) {
36
+ this.sock = sock
37
+ this.config = { ...DEFAULT_CONFIG, ...config }
38
+ this.recentContacts = []
39
+ this.unreadMessages = []
40
+ this.cycleTimer = null
41
+ this.isRunning = false
42
+ this.stats = {
43
+ cyclesExecuted: 0,
44
+ typingActionsPerformed: 0,
45
+ readReceiptsMarked: 0,
46
+ presenceToggles: 0,
47
+ errors: 0,
48
+ lastCycleAt: null,
49
+ nextCycleAt: null
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Start the entropy service.
55
+ * Call this after sock is connected.
56
+ */
57
+ start() {
58
+ if (!this.config.enabled) return
59
+ if (this.isRunning) return
60
+ this.isRunning = true
61
+ this._scheduleNextCycle()
62
+ }
63
+
64
+ /**
65
+ * Stop the entropy service.
66
+ */
67
+ stop() {
68
+ this.isRunning = false
69
+ if (this.cycleTimer) {
70
+ clearTimeout(this.cycleTimer)
71
+ this.cycleTimer = null
72
+ }
73
+ this.stats.nextCycleAt = null
74
+ }
75
+
76
+ /**
77
+ * Track an incoming message to build recent contacts list.
78
+ * Call this from messages.upsert event handler.
79
+ * @param {object} msg - Raw Baileys message
80
+ */
81
+ trackMessage(msg) {
82
+ try {
83
+ if (msg.key?.fromMe) return
84
+ const jid = msg.key?.remoteJid
85
+ if (!jid) return
86
+
87
+ const isGroup = jid.endsWith('@g.us')
88
+ const existingIdx = this.recentContacts.findIndex((c) => c.jid === jid)
89
+
90
+ if (existingIdx >= 0) {
91
+ this.recentContacts[existingIdx].lastMessageAt = new Date()
92
+ } else {
93
+ this.recentContacts.push({ jid, lastMessageAt: new Date(), isGroup })
94
+ }
95
+
96
+ if (this.recentContacts.length > this.config.maxRecentContacts) {
97
+ this.recentContacts.sort((a, b) => b.lastMessageAt - a.lastMessageAt)
98
+ this.recentContacts = this.recentContacts.slice(0, this.config.maxRecentContacts)
99
+ }
100
+
101
+ if (msg.key?.id && msg.message) {
102
+ this.unreadMessages.push({ jid, messageKey: msg.key, receivedAt: new Date() })
103
+ if (this.unreadMessages.length > 50) {
104
+ this.unreadMessages = this.unreadMessages.slice(-50)
105
+ }
106
+ }
107
+ } catch (err) {
108
+ this.stats.errors++
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Get current stats
114
+ */
115
+ getStats() {
116
+ return { ...this.stats }
117
+ }
118
+
119
+ _scheduleNextCycle() {
120
+ if (!this.isRunning) return
121
+ const delay = this._rand(this.config.minIntervalMs, this.config.maxIntervalMs)
122
+ this.stats.nextCycleAt = new Date(Date.now() + delay)
123
+ this.cycleTimer = setTimeout(() => {
124
+ this._executeCycle()
125
+ .catch(() => this.stats.errors++)
126
+ .finally(() => this._scheduleNextCycle())
127
+ }, delay)
128
+ }
129
+
130
+ async _executeCycle() {
131
+ if (!this.isRunning || this.recentContacts.length === 0) return
132
+
133
+ this.stats.cyclesExecuted++
134
+ this.stats.lastCycleAt = new Date()
135
+
136
+ const actions = []
137
+
138
+ if (Math.random() < this.config.typingProbability) {
139
+ actions.push(this._performTyping())
140
+ }
141
+ if (Math.random() < this.config.readReceiptProbability && this.unreadMessages.length > 0) {
142
+ actions.push(this._performReadReceipt())
143
+ }
144
+ if (Math.random() < this.config.presenceToggleProbability) {
145
+ actions.push(this._performPresenceToggle())
146
+ }
147
+
148
+ await Promise.allSettled(actions)
149
+ }
150
+
151
+ async _performTyping() {
152
+ try {
153
+ const eligible = this.recentContacts.filter((c) => !c.isGroup)
154
+ if (eligible.length === 0) return
155
+ const contact = eligible[Math.floor(Math.random() * eligible.length)]
156
+ const duration = this._rand(this.config.typingMinMs, this.config.typingMaxMs)
157
+
158
+ await this.sock.sendPresenceUpdate('composing', contact.jid)
159
+ await this._sleep(duration)
160
+ await this.sock.sendPresenceUpdate('paused', contact.jid)
161
+
162
+ this.stats.typingActionsPerformed++
163
+ } catch (err) {
164
+ this.stats.errors++
165
+ }
166
+ }
167
+
168
+ async _performReadReceipt() {
169
+ try {
170
+ const msg = this.unreadMessages[Math.floor(Math.random() * this.unreadMessages.length)]
171
+ if (!msg) return
172
+ const delay = this._rand(
173
+ this.config.readReceiptMinDelayMs,
174
+ this.config.readReceiptMaxDelayMs
175
+ )
176
+ await this._sleep(delay)
177
+ await this.sock.readMessages([msg.messageKey])
178
+ this.unreadMessages = this.unreadMessages.filter((m) => m !== msg)
179
+ this.stats.readReceiptsMarked++
180
+ } catch (err) {
181
+ this.stats.errors++
182
+ }
183
+ }
184
+
185
+ async _performPresenceToggle() {
186
+ try {
187
+ const duration = this._rand(
188
+ this.config.presenceToggleMinMs,
189
+ this.config.presenceToggleMaxMs
190
+ )
191
+ await this.sock.sendPresenceUpdate('available')
192
+ await this._sleep(duration)
193
+ await this.sock.sendPresenceUpdate('unavailable')
194
+ this.stats.presenceToggles++
195
+ } catch (err) {
196
+ this.stats.errors++
197
+ }
198
+ }
199
+
200
+ _rand(min, max) {
201
+ return Math.floor(Math.random() * (max - min + 1)) + min
202
+ }
203
+
204
+ _sleep(ms) {
205
+ return new Promise((resolve) => setTimeout(resolve, ms))
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Factory function
211
+ * @param {object} sock - Baileys WASocket
212
+ * @param {object} config - Optional config
213
+ */
214
+ const createHumanEntropyService = (sock, config = {}) => {
215
+ const service = new HumanEntropyService(sock, config)
216
+ return {
217
+ start: () => service.start(),
218
+ stop: () => service.stop(),
219
+ trackMessage: (msg) => service.trackMessage(msg),
220
+ getStats: () => service.getStats()
221
+ }
222
+ }
223
+
224
+ exports.HumanEntropyService = HumanEntropyService
225
+ exports.createHumanEntropyService = createHumanEntropyService
226
+ module.exports = { HumanEntropyService, createHumanEntropyService }