ishumdz-bail 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.
Files changed (118) hide show
  1. package/README.md +772 -0
  2. package/WAProto/fix-imports.js +85 -0
  3. package/WAProto/index.d.ts +79257 -0
  4. package/WAProto/index.js +242946 -0
  5. package/engine-requirements.js +10 -0
  6. package/lib/Defaults/index.js +142 -0
  7. package/lib/Games/index.js +497 -0
  8. package/lib/Signal/Group/ciphertext-message.js +12 -0
  9. package/lib/Signal/Group/group-session-builder.js +30 -0
  10. package/lib/Signal/Group/group_cipher.js +93 -0
  11. package/lib/Signal/Group/index.js +12 -0
  12. package/lib/Signal/Group/keyhelper.js +18 -0
  13. package/lib/Signal/Group/queue-job.js +53 -0
  14. package/lib/Signal/Group/sender-chain-key.js +26 -0
  15. package/lib/Signal/Group/sender-key-distribution-message.js +63 -0
  16. package/lib/Signal/Group/sender-key-message.js +66 -0
  17. package/lib/Signal/Group/sender-key-name.js +48 -0
  18. package/lib/Signal/Group/sender-key-record.js +41 -0
  19. package/lib/Signal/Group/sender-key-state.js +84 -0
  20. package/lib/Signal/Group/sender-message-key.js +26 -0
  21. package/lib/Signal/libsignal.js +431 -0
  22. package/lib/Signal/lid-mapping.js +277 -0
  23. package/lib/Socket/Client/index.js +3 -0
  24. package/lib/Socket/Client/types.js +11 -0
  25. package/lib/Socket/Client/websocket.js +84 -0
  26. package/lib/Socket/ban-checker.js +265 -0
  27. package/lib/Socket/business.js +379 -0
  28. package/lib/Socket/chats.js +1193 -0
  29. package/lib/Socket/communities.js +431 -0
  30. package/lib/Socket/groups.js +374 -0
  31. package/lib/Socket/index.js +13 -0
  32. package/lib/Socket/luxu.js +460 -0
  33. package/lib/Socket/messages-recv.js +1916 -0
  34. package/lib/Socket/messages-send.js +1469 -0
  35. package/lib/Socket/mex.js +41 -0
  36. package/lib/Socket/newsletter.js +261 -0
  37. package/lib/Socket/socket.js +988 -0
  38. package/lib/Socket/username.js +234 -0
  39. package/lib/Store/index.js +10 -0
  40. package/lib/Store/keyed-db.js +108 -0
  41. package/lib/Store/make-cache-manager-store.js +85 -0
  42. package/lib/Store/make-in-memory-store.js +198 -0
  43. package/lib/Store/make-ordered-dictionary.js +75 -0
  44. package/lib/Store/object-repository.js +32 -0
  45. package/lib/Types/Auth.js +2 -0
  46. package/lib/Types/Bussines.js +2 -0
  47. package/lib/Types/Call.js +2 -0
  48. package/lib/Types/Chat.js +8 -0
  49. package/lib/Types/Contact.js +2 -0
  50. package/lib/Types/Events.js +2 -0
  51. package/lib/Types/GroupMetadata.js +2 -0
  52. package/lib/Types/Label.js +25 -0
  53. package/lib/Types/LabelAssociation.js +7 -0
  54. package/lib/Types/Message.js +11 -0
  55. package/lib/Types/Mex.js +37 -0
  56. package/lib/Types/Product.js +2 -0
  57. package/lib/Types/Signal.js +2 -0
  58. package/lib/Types/Socket.js +3 -0
  59. package/lib/Types/State.js +56 -0
  60. package/lib/Types/USync.js +2 -0
  61. package/lib/Types/index.js +26 -0
  62. package/lib/Utils/auth-utils.js +302 -0
  63. package/lib/Utils/browser-utils.js +49 -0
  64. package/lib/Utils/business.js +231 -0
  65. package/lib/Utils/chat-utils.js +872 -0
  66. package/lib/Utils/classify-disconnect.js +126 -0
  67. package/lib/Utils/companion-reg-client-utils.js +35 -0
  68. package/lib/Utils/crypto.js +118 -0
  69. package/lib/Utils/decode-wa-message.js +350 -0
  70. package/lib/Utils/event-buffer.js +622 -0
  71. package/lib/Utils/generics.js +403 -0
  72. package/lib/Utils/history.js +134 -0
  73. package/lib/Utils/identity-change-handler.js +50 -0
  74. package/lib/Utils/index.js +23 -0
  75. package/lib/Utils/link-preview.js +85 -0
  76. package/lib/Utils/logger.js +3 -0
  77. package/lib/Utils/lt-hash.js +8 -0
  78. package/lib/Utils/make-mutex.js +33 -0
  79. package/lib/Utils/message-composer.js +273 -0
  80. package/lib/Utils/message-retry-manager.js +265 -0
  81. package/lib/Utils/messages-media.js +793 -0
  82. package/lib/Utils/messages.js +1586 -0
  83. package/lib/Utils/noise-handler.js +201 -0
  84. package/lib/Utils/offline-node-processor.js +40 -0
  85. package/lib/Utils/pre-key-manager.js +106 -0
  86. package/lib/Utils/process-message.js +630 -0
  87. package/lib/Utils/rate-limiter.js +228 -0
  88. package/lib/Utils/reporting-utils.js +258 -0
  89. package/lib/Utils/signal.js +201 -0
  90. package/lib/Utils/stanza-ack.js +38 -0
  91. package/lib/Utils/sync-action-utils.js +49 -0
  92. package/lib/Utils/tc-token-utils.js +163 -0
  93. package/lib/Utils/use-multi-file-auth-state.js +121 -0
  94. package/lib/Utils/validate-connection.js +203 -0
  95. package/lib/WABinary/constants.js +1301 -0
  96. package/lib/WABinary/decode.js +262 -0
  97. package/lib/WABinary/encode.js +220 -0
  98. package/lib/WABinary/generic-utils.js +204 -0
  99. package/lib/WABinary/index.js +6 -0
  100. package/lib/WABinary/jid-utils.js +98 -0
  101. package/lib/WABinary/types.js +2 -0
  102. package/lib/WAM/BinaryInfo.js +10 -0
  103. package/lib/WAM/constants.js +22853 -0
  104. package/lib/WAM/encode.js +150 -0
  105. package/lib/WAM/index.js +4 -0
  106. package/lib/WAUSync/Protocols/USyncContactProtocol.js +52 -0
  107. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +54 -0
  108. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -0
  109. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +38 -0
  110. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
  111. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +51 -0
  112. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +29 -0
  113. package/lib/WAUSync/Protocols/index.js +6 -0
  114. package/lib/WAUSync/USyncQuery.js +98 -0
  115. package/lib/WAUSync/USyncUser.js +31 -0
  116. package/lib/WAUSync/index.js +4 -0
  117. package/lib/index.js +37 -0
  118. package/package.json +150 -0
package/README.md ADDED
@@ -0,0 +1,772 @@
1
+ <div align="center">
2
+ <img src="https://capsule-render.vercel.app/api?type=waving&height=220&color=0:ff6b6b,40:f06595,100:845ef7&text=ishumdz-bail&fontAlignY=40&fontSize=44&fontColor=ffffff&desc=Stable%20WhatsApp%20Web%20API%20Fork%20for%20Production%20Bots&descAlignY=60&descSize=16" alt="Header Banner" />
3
+
4
+ <br/>
5
+
6
+ <!-- Rounded + border image -->
7
+ <a href="https://ishanx-pro.site.je">
8
+ <kbd>
9
+ <img src="https://i.ibb.co/KjfHTDhN/file-00000000a86881f8801b23682cb9bf66.png" alt="WhatsApp Baileys 2026" width="720" />
10
+ </kbd>
11
+ </a>
12
+
13
+ <br/><br/>
14
+
15
+
16
+ # 🧑‍💻 ishumdz-bail
17
+
18
+ <p>
19
+ <img src="https://img.shields.io/badge/Node.js-%3E%3D20-339933?style=for-the-badge&logo=nodedotjs&logoColor=white" />
20
+ <img src="https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" />
21
+ <img src="https://img.shields.io/badge/WebSocket-010101?style=for-the-badge&logo=socketdotio&logoColor=white" />
22
+ <img src="https://img.shields.io/badge/Open%20Source-FF4500?style=for-the-badge&logo=github&logoColor=white" />
23
+ <img src="https://img.shields.io/badge/license-MIT-blue?style=for-the-badge" />
24
+ </p>
25
+
26
+ <p>
27
+ <img src="https://img.shields.io/npm/v/ishumdz-bail?style=flat-square&color=25D366&label=npm" />
28
+ <img src="https://img.shields.io/badge/maintained%20by-Lovely-black?style=flat-square" />
29
+ </p>
30
+
31
+ **Open-source WhatsApp automation library — no browser required.**
32
+ Built on WebSocket for speed, stability, and full multi-device support.
33
+
34
+ <br/>
35
+
36
+ [Installation](#-getting-started) • [Features](#-main-features) • [Stability](#-stability--disconnect-handling) • [Website](https://ishanx-pro.site.je) • [WhatsApp Channel](https://shyracore.indevs.in)
37
+
38
+ </div>
39
+
40
+ ---
41
+
42
+ ## ✨ What is ishumdz-bail?
43
+
44
+ **ishumdz-bail** (`ishumdz-bail`) is a powerful, open-source WhatsApp Web library built on top of the Baileys protocol stack — extended with features not found in any other public fork. It connects directly to WhatsApp's multi-device WebSocket protocol. No Selenium, no Puppeteer, no browser overhead.
45
+
46
+ > ⚡ **Node.js ≥ 20 required.**
47
+
48
+ ---
49
+
50
+ ## 🚀 Getting Started
51
+
52
+ ```bash
53
+ npm install ishumdz-bail
54
+ ```
55
+
56
+ ```javascript
57
+ import { makeWASocket, useMultiFileAuthState } from 'ishumdz-bail'
58
+
59
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info')
60
+ const sock = makeWASocket({
61
+ auth: state,
62
+ syncFullHistory: false, // skip history sync — bot works immediately
63
+ aiLabel: true, // stamp messages with AI bot marker (default: true)
64
+ })
65
+
66
+ sock.ev.on('creds.update', saveCreds)
67
+ ```
68
+
69
+ ---
70
+
71
+ ## 🧩 Main Features
72
+
73
+ | Feature | Description |
74
+ |---|---|
75
+ | 💬 **Rich Response (GenAI Bubble)** | Send Meta AI-style messages: markdown, code blocks, tables, LaTeX, maps, inline images, HTML — rendered natively as GenAI bubble in WA client |
76
+ | 🚫 **4-Factor Ban Checker** | Detect ban status via 4 independent signals: live registry, public send-page, identity-key probe, device-count signature |
77
+ | 🆔 **Username Socket (w:mex)** | Full WA username API: check availability, set, delete, pin, find by username, fetch recommendations — via WhatsApp's internal Pando/MEX GraphQL protocol |
78
+ | 🏘️ **Communities Socket** | Full community management: create, link/unlink groups, manage participants, invite codes, ephemeral toggle, approval mode |
79
+ | 🔕 **noSelfSync** | Skip syncing outgoing messages to your own other devices — reduces noise and bandwidth. Includes silent-drop guard (throws 421 instead of pretending the send succeeded) |
80
+ | ⚙️ **Rust-powered Crypto** | `md5`, `hkdf`, LT-Hash anti-tampering offloaded to `whatsapp-rust-bridge` native module for raw speed |
81
+ | 🗂️ **LID Mapping Store** | Persistent LID ↔ phone-number bi-directional cache with LRU eviction and in-flight dedup — prevents duplicate USync lookups |
82
+ | 🔐 **Pre-Key Manager** | Concurrency-safe Signal pre-key operations via per-key-type PQueue — no race conditions on key updates/deletions |
83
+ | 🔄 **Classify Disconnect** | Maps every WA disconnect code to `{ category, shouldReconnect, backoffMs }` — properly handles code 515 (restartRequired) as recoverable, not fatal |
84
+ | ⏱️ **Rate Limiter** | Anti-spam pacing calculator: enforces per-minute/hour/day caps, burst allowance, new-chat delays, identical-message dedup |
85
+ | 🖼️ **Album Message** | Send multiple images/videos as a single WA album/grid, with per-item or top-level caption and `gifPlayback` support |
86
+ | 🤖 **AI Label Config** | `aiLabel: true/false` in socket config — controls whether outgoing messages carry the `biz_bot` attribute that WA uses to render the AI icon |
87
+ | 🔎 **USync Username Protocol** | Username resolution baked into USync queries — resolve WA usernames alongside contacts in a single round-trip |
88
+ | 📥 **Offline Node Processor** | Batch-processes pending stanzas received while offline, preventing message loss on reconnect |
89
+ | 🔑 **Identity Change Handler** | Dedicated handler for Signal identity key changes — prevents session corruption when a contact re-registers |
90
+ | 📣 **Newsletter/Channel Media Upload** | Full support for uploading images, videos, audio, stickers to channels using correct `/newsletter/newsletter-*` paths |
91
+ | 😀 **Newsletter Reactions** | React to channel messages with emojis, track votes, and manage newsletter engagement |
92
+ | 📊 **Poll Voting** | Create polls, track encrypted votes, display results, and support multiple selection polls |
93
+ | 🎮 **Built-in Games** | 8 games: Blackjack, Slots, Dice, Coin Flip, Roulette, Mines, Trivia, Rock Paper Scissors |
94
+
95
+ ---
96
+
97
+ ## 💬 Rich Response (GenAI Bubble)
98
+
99
+ Send messages that render as Meta AI-style bubbles inside WhatsApp. Supports multiple primitives in a single message:
100
+
101
+ ```javascript
102
+ // Markdown text
103
+ await sock.sendMessage(jid, {
104
+ richResponse: {
105
+ text: '**Hello** from *ishumdz-bail*',
106
+ responseId: 'optional-uuid'
107
+ }
108
+ })
109
+
110
+ // Code block
111
+ await sock.sendMessage(jid, {
112
+ richResponse: {
113
+ code: 'console.log("hello")',
114
+ language: 'javascript'
115
+ }
116
+ })
117
+
118
+ // Table
119
+ await sock.sendMessage(jid, {
120
+ richResponse: {
121
+ table: {
122
+ rows: [
123
+ ['Name', 'Age'],
124
+ ['Alice', '25'],
125
+ ['Bob', '30']
126
+ ]
127
+ }
128
+ }
129
+ })
130
+
131
+ // HTML (raw HTML rendered in client)
132
+ await sock.sendMessage(jid, {
133
+ richResponse: {
134
+ text: 'fallback',
135
+ html: '<b>bold</b> <a href="https://example.com">link</a>'
136
+ }
137
+ })
138
+
139
+ // LaTeX
140
+ await sock.sendMessage(jid, {
141
+ richResponse: {
142
+ latex: 'E = mc^2'
143
+ }
144
+ })
145
+
146
+ // Map / location
147
+ await sock.sendMessage(jid, {
148
+ richResponse: {
149
+ map: {
150
+ latitude: -6.2,
151
+ longitude: 106.8,
152
+ zoom: 15,
153
+ title: 'Jakarta',
154
+ annotations: []
155
+ }
156
+ }
157
+ })
158
+
159
+ // Inline image
160
+ await sock.sendMessage(jid, {
161
+ richResponse: {
162
+ imageUrl: 'https://example.com/photo.jpg'
163
+ }
164
+ })
165
+ ```
166
+
167
+ **Shortcut methods** (all accept `quoted` and `options`):
168
+
169
+ ```javascript
170
+ await sock.sendTable(jid, 'Title', ['H1','H2'], [['A','B']], quoted)
171
+ await sock.sendList(jid, 'Title', ['item1','item2'], quoted)
172
+ await sock.sendCodeBlock(jid, 'print("hello")', quoted, { language: 'python' })
173
+ await sock.sendLatex(jid, quoted, { latex: 'x^2 + y^2 = z^2' })
174
+ await sock.sendRichMessage(jid, submessages, quoted)
175
+ ```
176
+
177
+ ---
178
+
179
+ ## 🖼️ Album Message
180
+
181
+ Send multiple images/videos grouped into a single WA album:
182
+
183
+ ```javascript
184
+ await sock.sendMessage(jid, {
185
+ album: [
186
+ { image: { url: 'https://example.com/a.jpg' } },
187
+ { image: { url: 'https://example.com/b.jpg' }, caption: 'caption foto kedua' },
188
+ { video: { url: 'https://example.com/c.mp4' }, gifPlayback: false }
189
+ ],
190
+ caption: 'caption ini otomatis ke item pertama'
191
+ })
192
+ ```
193
+
194
+ ---
195
+
196
+ ## 🚫 Ban Checker
197
+
198
+ 4-factor ban detection against WhatsApp's own servers — no third-party API:
199
+
200
+ ```javascript
201
+ const result = await sock.checkBanStatus('628123456789')
202
+ // or: sock.checkBanStatus('628123456789@s.whatsapp.net')
203
+
204
+ console.log(result)
205
+ // {
206
+ // status: 'ACTIVE' | 'PROFILE_HIDDEN' | 'LIKELY_ACTIVE' | 'BANNED' | 'OFF_WHATSAPP' | 'UNKNOWN',
207
+ // emoji: '🟢' | '🟡' | '🔴' | '❓',
208
+ // confidence: 0..1,
209
+ // deviceCount: number | null,
210
+ // registryExists: boolean | null,
211
+ // pageVisible: boolean | null,
212
+ // profileName: string | null
213
+ // }
214
+ ```
215
+
216
+ **Four factors checked:**
217
+ - **Factor A** — Live registry (`sock.onWhatsApp`)
218
+ - **Factor B** — Public send-page title/image probe (`api.whatsapp.com`)
219
+ - **Factor C** — Identity-key device probe via USync (strongest: banned numbers have their keys destroyed)
220
+ - **Factor D** — Device-count signature (2+ = ACTIVE, 1 generic = likely BANNED, 0 = BANNED/OFF_WA)
221
+
222
+ ---
223
+
224
+ ## 🆔 Username Socket (w:mex)
225
+
226
+ Full WA `@username` API via WhatsApp's internal Pando/MEX GraphQL protocol, query IDs sourced from Java decompile of WA 2.26.17.2:
227
+
228
+ ```javascript
229
+ // Check availability
230
+ const res = await sock.checkUsername('myusername')
231
+ // { available: true, username } or { available: false, suggestions: [...] }
232
+
233
+ // Set username
234
+ await sock.setUsername('myusername')
235
+
236
+ // Delete username
237
+ await sock.deleteUsername()
238
+
239
+ // Get your own username
240
+ const mine = await sock.getMyUsername()
241
+
242
+ // Pin/unpin username
243
+ await sock.setUsernamePin(true)
244
+
245
+ // Find user by username
246
+ const user = await sock.findUserByUsername('someuser', pin)
247
+
248
+ // Fetch usernames of your contacts in batch
249
+ const usernames = await sock.fetchContactUsernames('94xxxx@s.whatsapp.net', '628yyy@s.whatsapp.net')
250
+
251
+ // Get username suggestions
252
+ const suggestions = await sock.getUsernameRecommendations()
253
+ ```
254
+
255
+ ---
256
+
257
+ ## 🏘️ Communities Socket
258
+
259
+ ```javascript
260
+ // Create community
261
+ const community = await sock.communityCreate('Community Name', 'Description')
262
+
263
+ // Create group inside community
264
+ await sock.communityCreateGroup('Group Name', [jid1, jid2], communityJid)
265
+
266
+ // Link/unlink existing group
267
+ await sock.communityLinkGroup(groupJid, communityJid)
268
+ await sock.communityUnlinkGroup(groupJid, communityJid)
269
+
270
+ // Fetch linked groups
271
+ const groups = await sock.communityFetchLinkedGroups(communityJid)
272
+
273
+ // Manage participants
274
+ await sock.communityParticipantsUpdate(communityJid, [jid1], 'add') // 'add' | 'remove' | 'promote' | 'demote'
275
+
276
+ // Invite code
277
+ const code = await sock.communityInviteCode(communityJid)
278
+ await sock.communityRevokeInvite(communityJid)
279
+ await sock.communityAcceptInvite(code)
280
+
281
+ // Settings
282
+ await sock.communityToggleEphemeral(communityJid, 86400) // seconds
283
+ await sock.communityMemberAddMode(communityJid, 'admin_add')
284
+ await sock.communityJoinApprovalMode(communityJid, 'on')
285
+ await sock.communityUpdateSubject(communityJid, 'New Name')
286
+ await sock.communityUpdateDescription(communityJid, 'New Desc')
287
+ await sock.communityLeave(communityJid)
288
+ ```
289
+
290
+ ---
291
+
292
+ ## 🔕 noSelfSync
293
+
294
+ Skip syncing outgoing messages to your own linked devices. Useful for high-volume bots where sync traffic is unnecessary:
295
+
296
+ ```javascript
297
+ await sock.sendMessage(jid, { text: 'hello' }, { noSelfSync: true })
298
+
299
+ // Also supported in all shortcut methods:
300
+ await sock.sendTable(jid, title, headers, rows, quoted, { noSelfSync: true })
301
+ await sock.sendCodeBlock(jid, code, quoted, { noSelfSync: true })
302
+ ```
303
+
304
+ > **Safe by design:** if `noSelfSync` would accidentally drop all recipients (e.g. messaging yourself), the guard kicks in and delivers normally. If the other party has zero resolved devices, it throws `Boom 421` instead of silently pretending the message was sent.
305
+
306
+ ---
307
+
308
+ ## 🔄 Stability & Disconnect Handling
309
+
310
+ ishumdz-bail ships `classifyDisconnect()` — maps every WA status code into an actionable result:
311
+
312
+ ```javascript
313
+ import { classifyDisconnect } from 'ishumdz-bail'
314
+
315
+ sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
316
+ if (connection === 'close') {
317
+ const code = lastDisconnect?.error?.output?.statusCode
318
+ const info = classifyDisconnect(code)
319
+
320
+ console.log(info)
321
+ // {
322
+ // category: 'fatal' | 'recoverable' | 'rate-limited' | 'unknown',
323
+ // shouldReconnect: boolean,
324
+ // backoffMs: number, // ms to wait before reconnecting
325
+ // message: string,
326
+ // code: number
327
+ // }
328
+
329
+ if (info.shouldReconnect) {
330
+ setTimeout(() => reconnect(), info.backoffMs)
331
+ }
332
+ }
333
+ })
334
+ ```
335
+
336
+ **Code map:**
337
+
338
+ | Code | Category | Reconnect | Backoff |
339
+ |---|---|---|---|
340
+ | 401, 440 | fatal | ❌ | — |
341
+ | 515 | recoverable | ✅ | 0 ms (immediate) |
342
+ | 405 | fatal | ❌ | — |
343
+ | 408 | recoverable | ✅ | 30 s |
344
+ | 503 | recoverable | ✅ | 5 min |
345
+ | 429 | rate-limited | ✅ | 60 s |
346
+ | 500 | recoverable | ✅ | 5 s |
347
+ | 503 | recoverable | ✅ | 10 s |
348
+ | Graceful close | recoverable | ✅ | 2 s |
349
+ | Unknown | unknown | ✅ | 15 s |
350
+
351
+ > **Important:** Code 515 (`restartRequired`) is WhatsApp's normal post-pairing signal. ishumdz-bail correctly treats it as recoverable with 0 ms backoff — other forks incorrectly mark it as fatal, causing bots to stop after first pair.
352
+
353
+ ---
354
+
355
+ ## ⏱️ Rate Limiter
356
+
357
+ Anti-ban pacing calculator — wire into your send path before each `sendMessage`:
358
+
359
+ ```javascript
360
+ import { RateLimiter } from 'ishumdz-bail'
361
+
362
+ const limiter = new RateLimiter({
363
+ maxPerMinute: 8,
364
+ maxPerHour: 200,
365
+ maxPerDay: 1500,
366
+ minDelayMs: 1500,
367
+ maxDelayMs: 5000,
368
+ newChatDelayMs: 3000,
369
+ maxIdenticalMessages: 3,
370
+ burstAllowance: 3
371
+ })
372
+
373
+ async function safeSend(jid, content) {
374
+ const delay = await limiter.getDelay(jid, content)
375
+ if (delay === -1) throw new Error('Rate limit exceeded — blocked')
376
+ if (delay > 0) await new Promise(r => setTimeout(r, delay))
377
+ await sock.sendMessage(jid, content)
378
+ limiter.record(jid, content)
379
+ }
380
+ ```
381
+
382
+ ---
383
+
384
+ ## 📦 Supported Message Types
385
+
386
+ Every WhatsApp message type is covered:
387
+
388
+ - Text, image, video, audio, document, sticker, GIF/video note (PTV)
389
+ - Location & live location
390
+ - Contact / vCard
391
+ - Poll (create, vote, add option, poll result)
392
+ - Button, list, template, interactive (native flow)
393
+ - Album (multiple media in one message)
394
+ - Event & event invite
395
+ - Group invite, group status, group mention
396
+ - Spoiler (blurred) messages
397
+ - Reaction & edited message
398
+ - View-once media
399
+ - Status/story mention & reply
400
+ - Newsletter / channel messages
401
+ - Payment & payment invite
402
+ - All WhatsApp Business types: product, catalog, order, invoice, business profile
403
+
404
+ <details>
405
+ <summary><b>Example: Album</b></summary>
406
+
407
+ ```javascript
408
+ await sock.sendMessage(jid, {
409
+ album: [
410
+ { image: { url: 'https://example.com/1.jpg' } },
411
+ { video: { url: 'https://example.com/2.mp4' } }
412
+ ],
413
+ caption: 'Album caption'
414
+ })
415
+ ```
416
+ </details>
417
+
418
+ <details>
419
+ <summary><b>Example: Poll</b></summary>
420
+
421
+ ```javascript
422
+ await sock.sendMessage(jid, {
423
+ poll: {
424
+ name: 'Poll Title',
425
+ values: ['Option A', 'Option B'],
426
+ selectableCount: 1
427
+ }
428
+ })
429
+ ```
430
+ </details>
431
+
432
+ <details>
433
+ <summary><b>Example: Spoiler</b></summary>
434
+
435
+ ```javascript
436
+ await sock.sendMessage(jid, {
437
+ text: 'Spoiler content',
438
+ spoiler: true
439
+ })
440
+ ```
441
+ </details>
442
+
443
+ <details>
444
+ <summary><b>Example: Event</b></summary>
445
+
446
+ ```javascript
447
+ await sock.sendMessage(jid, {
448
+ eventMessage: {
449
+ name: 'Meeting',
450
+ description: 'Weekly sync',
451
+ location: { degreesLatitude: -6.2, degreesLongitude: 106.8 },
452
+ startTime: Math.floor(Date.now() / 1000) + 3600
453
+ }
454
+ })
455
+ ```
456
+ </details>
457
+
458
+ ---
459
+
460
+ ## 🛠️ Additional Methods
461
+
462
+ ```javascript
463
+ // Parse incoming extended/special messages
464
+ sock.ev.on('messages.upsert', ({ messages }) => {
465
+ const extended = sock.parseExtendedMessageContent(messages[0].message)
466
+ if (extended) console.log(extended.type, extended.data)
467
+ })
468
+
469
+ // Business profile
470
+ const profile = await sock.getBusinessProfile(jid)
471
+ await sock.updateBusinessProfile({ description: 'Open 9-5', email: 'hi@example.com', category: 'Retail' })
472
+
473
+ // Get newsletter/channel JID from URL
474
+ await sock.newsletterId('https://whatsapp.com/channel/...')
475
+
476
+ // Refresh media URL for expired messages
477
+ await sock.updateMediaMessage(message)
478
+ ```
479
+
480
+ ---
481
+
482
+ ## 🎮 Games
483
+
484
+ Built-in games for your WhatsApp bot! Import from `ishumdz-bail`:
485
+
486
+ ```javascript
487
+ import {
488
+ blackjack, slotMachine, diceGame,
489
+ coinFlip, roulette, rps, trivia,
490
+ createMines, revealTile, cashoutMines
491
+ } from 'ishumdz-bail'
492
+ ```
493
+
494
+ ### 🃏 Blackjack
495
+
496
+ ```javascript
497
+ // Start game
498
+ const game = blackjack('start', [], [], 1000)
499
+ await sock.sendMessage(jid, { text: game.message })
500
+
501
+ // Hit (after start)
502
+ const hit = blackjack('hit', game.playerHand, game.dealerHand, 1000)
503
+
504
+ // Stand
505
+ const stand = blackjack('stand', game)
506
+
507
+ // Double
508
+ const dbl = blackjack('double', game)
509
+ ```
510
+
511
+ ### 🎰 Slot Machine
512
+
513
+ ```javascript
514
+ const slot = slotMachine(100)
515
+ await sock.sendMessage(jid, { text: slot.message })
516
+ // 🎰 [🍒] [🍋] [💎] - NO MATCH
517
+ ```
518
+
519
+ ### 🎲 Dice
520
+
521
+ ```javascript
522
+ const dice = diceGame(100, 'high') // high, low, or seven
523
+ await sock.sendMessage(jid, { text: dice.message })
524
+ ```
525
+
526
+ ### 🪙 Coin Flip
527
+
528
+ ```javascript
529
+ const coin = coinFlip(100, 'heads') // heads or tails
530
+ await sock.sendMessage(jid, { text: coin.message })
531
+ ```
532
+
533
+ ### 🎰 Roulette
534
+
535
+ ```javascript
536
+ const rou = roulette(100, 'red') // red, black, odd, even, low, high
537
+ await sock.sendMessage(jid, { text: rou.message })
538
+ ```
539
+
540
+ ### ✊ Rock Paper Scissors
541
+
542
+ ```javascript
543
+ const r = rps('rock') // rock, paper, scissors
544
+ await sock.sendMessage(jid, { text: r.message })
545
+ ```
546
+
547
+ ### 💣 Mines
548
+
549
+ ```javascript
550
+ // Create game
551
+ const game = createMines(5, 5, 5) // rows, cols, mines
552
+
553
+ // Reveal tile
554
+ const result = revealTile(game, 0, 0) // row, col
555
+ await sock.sendMessage(jid, { text: result.message })
556
+
557
+ // Cashout
558
+ const cashout = cashoutMines(game, 100)
559
+ await sock.sendMessage(jid, { text: cashout.message })
560
+ ```
561
+
562
+ ### 🧠 Trivia
563
+
564
+ ```javascript
565
+ const quiz = trivia(100)
566
+ await sock.sendMessage(jid, { text: quiz.message })
567
+
568
+ // Check answer (A, B, C, or D)
569
+ const answer = checkTriviaAnswer('B', quiz.answer, 100)
570
+ await sock.sendMessage(jid, { text: answer.message })
571
+ ```
572
+
573
+ ### 📱 Bot Command Example
574
+
575
+ ```javascript
576
+ sock.ev.on('messages.upsert', async ({ messages }) => {
577
+ const msg = messages[0]
578
+ const text = msg.message?.conversation || ''
579
+
580
+ if (text === '.rps rock' || text === '.rps paper' || text === '.rps scissors') {
581
+ const choice = text.split(' ')[1]
582
+ const result = rps(choice)
583
+ await sock.sendMessage(msg.key.remoteJid, { text: result.message })
584
+ }
585
+
586
+ if (text.startsWith('.slot')) {
587
+ const bet = parseInt(text.split(' ')[1]) || 100
588
+ const result = slotMachine(bet)
589
+ await sock.sendMessage(msg.key.remoteJid, { text: result.message })
590
+ }
591
+
592
+ if (text.startsWith('.coinflip')) {
593
+ const choice = text.split(' ')[1] || 'heads'
594
+ const bet = parseInt(text.split(' ')[2]) || 100
595
+ const result = coinFlip(bet, choice)
596
+ await sock.sendMessage(msg.key.remoteJid, { text: result.message })
597
+ }
598
+ })
599
+ ```
600
+
601
+ ---
602
+
603
+ ## 📊 Poll Voting
604
+
605
+ Create polls, track votes, and display results.
606
+
607
+ ### 🗳️ Create Poll
608
+
609
+ ```javascript
610
+ await sock.sendMessage(jid, {
611
+ poll: {
612
+ name: 'Best programming language?',
613
+ values: ['JavaScript', 'Python', 'Java', 'Go', 'Rust'],
614
+ selectableCount: 1
615
+ }
616
+ })
617
+ ```
618
+
619
+ ### 📊 Poll with Multiple Selections
620
+
621
+ ```javascript
622
+ await sock.sendMessage(jid, {
623
+ poll: {
624
+ name: 'Which features do you want?',
625
+ values: ['Games', 'AI', 'Stickers', 'Download'],
626
+ selectableCount: 3 // Users can select up to 3 options
627
+ }
628
+ })
629
+ ```
630
+
631
+ ### 📢 Announcement Group Poll (Admin Only Voting)
632
+
633
+ ```javascript
634
+ await sock.sendMessage(groupJid, {
635
+ poll: {
636
+ name: 'Admin Poll',
637
+ values: ['Option 1', 'Option 2'],
638
+ selectableCount: 1,
639
+ toAnnouncementGroup: true
640
+ }
641
+ })
642
+ ```
643
+
644
+ ### 🏆 Poll Result (Fake Results)
645
+
646
+ ```javascript
647
+ await sock.sendMessage(jid, {
648
+ pollResult: {
649
+ name: 'Best framework?',
650
+ votes: [['React', 150], ['Vue', 120], ['Angular', 80]]
651
+ }
652
+ })
653
+ ```
654
+
655
+ ### 📈 Track Poll Votes
656
+
657
+ ```javascript
658
+ import { getAggregateVotesInPollMessage } from 'ishumdz-bail'
659
+
660
+ // Store messages
661
+ const messageStore = new Map()
662
+
663
+ sock.ev.on('messages.upsert', async ({ messages }) => {
664
+ for (const msg of messages) {
665
+ const id = msg.key.remoteJid + ':' + msg.key.id
666
+ messageStore.set(id, msg)
667
+ }
668
+ })
669
+
670
+ // Listen for poll votes
671
+ sock.ev.on('messages.update', async (events) => {
672
+ for (const { key, update } of events) {
673
+ if (update.pollUpdates) {
674
+ const id = key.remoteJid + ':' + key.id
675
+ const pollCreation = messageStore.get(id)
676
+
677
+ if (pollCreation) {
678
+ const votes = getAggregateVotesInPollMessage({
679
+ message: pollCreation,
680
+ pollUpdates: update.pollUpdates
681
+ })
682
+
683
+ console.log('Poll votes:', votes)
684
+ // [{ name: 'Option 1', voters: ['123@s.whatsapp.net'] }, ...]
685
+ }
686
+ }
687
+ }
688
+ })
689
+ ```
690
+
691
+ ### 📱 Poll Bot Command Example
692
+
693
+ ```javascript
694
+ sock.ev.on('messages.upsert', async ({ messages }) => {
695
+ const msg = messages[0]
696
+ const text = msg.message?.conversation || ''
697
+
698
+ // .poll Question | Option1 | Option2 | Option3
699
+ if (text.startsWith('.poll')) {
700
+ const args = text.slice(5).split('|').map(s => s.trim())
701
+ const question = args[0]
702
+ const options = args.slice(1)
703
+
704
+ if (question && options.length >= 2) {
705
+ await sock.sendMessage(msg.key.remoteJid, {
706
+ poll: {
707
+ name: question,
708
+ values: options,
709
+ selectableCount: 1
710
+ }
711
+ })
712
+ }
713
+ }
714
+
715
+ // .pollresult React | 150 | Vue | 120
716
+ if (text.startsWith('.pollresult')) {
717
+ const args = text.slice(12).split('|').map(s => s.trim())
718
+ const votes = []
719
+ for (let i = 0; i < args.length; i += 2) {
720
+ votes.push([args[i], parseInt(args[i + 1]) || 0])
721
+ }
722
+
723
+ await sock.sendMessage(msg.key.remoteJid, {
724
+ pollResult: {
725
+ name: 'Poll Results',
726
+ votes
727
+ }
728
+ })
729
+ }
730
+ })
731
+ ```
732
+
733
+ ---
734
+
735
+ ## 🌐 Community & Support
736
+
737
+ <div align="center">
738
+
739
+ <table>
740
+ <tr>
741
+ <td align="center">
742
+ <a href="https://ishanx-pro.site.je">
743
+ 🌐<br/><b>Website</b><br/>ishanx-pro.site.je
744
+ </a>
745
+ </td>
746
+ <td align="center">
747
+ <a href="https://shyracore.indevs.in">
748
+ 💬<br/><b>WhatsApp Channel</b><br/>shyracore.indevs.in
749
+ </a>
750
+ </td>
751
+ </tr>
752
+ </table>
753
+
754
+ **Developer:** Lovely
755
+
756
+ </div>
757
+
758
+ ---
759
+
760
+ <div align="center">
761
+
762
+ ### ⭐ If this project helped you, consider giving it a star!
763
+
764
+ Made with ❤️ by **Lovely**
765
+
766
+ </div>
767
+
768
+ ---
769
+
770
+ ## 📄 License
771
+
772
+ MIT