ishumdz-bail 1.0.10 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,378 +1,1085 @@
1
1
  <div align="center">
2
-
3
- ```
4
- ╔═══════════════════════════════════════════════════════════════════════════╗
5
- ║ 📱 MAIN FEATURES ║
6
- ╠═══════════════════════════════════════════════════════════════════════════╣
7
- ║ ║
8
- ║ ┌─────────────────────────────────────────────────────────────────────┐ ║
9
- ║ │ 🎮 GAMES │ 📞 VOIP CALLER │ ⚡ PRO METHODS │ ║
10
- ║ │ ├─ Blackjack │ ├─ Auto Answer │ ├─ sendPoll │ ║
11
- ║ │ ├─ Slots │ ├─ Audio Playback │ ├─ sendPollVote │ ║
12
- ║ │ ├─ Dice │ └─ VoipClient │ ├─ editMessage │ ║
13
- ║ │ ├─ Coin Flip │ │ ├─ deleteMessage │ ║
14
- ║ │ ├─ Roulette │ 📊 POLLS │ ├─ pinMessage │ ║
15
- ║ │ ├─ Mines │ ├─ Create Poll │ ├─ starMessage │ ║
16
- ║ │ ├─ Trivia │ ├─ Vote Poll │ ├─ reactMessage │ ║
17
- ║ │ └─ RPS │ └─ Get Results │ ├─ sendPresence │ ║
18
- ║ └─────────────────────────────────────────────────────────────────────┘ ║
19
- ║ ║
20
- ║ ┌─────────────────────────────────────────────────────────────────────┐ ║
21
- ║ │ 📢 NEWSLETTER │ 🟢 STATUS │ 💬 CHAT │ ║
22
- ║ │ ├─ channelVote │ ├─ sendText │ ├─ editMessage │ ║
23
- ║ │ ├─ newsletterReact │ ├─ sendMedia │ ├─ deleteMessage │ ║
24
- ║ │ ├─ getMessages │ ├─ readStatus │ ├─ pinMessage │ ║
25
- ║ │ ├─ searchChannels │ └─ reactStatus │ ├─ unpinMessage │ ║
26
- ║ │ └─ listChannels │ │ ├─ starMessage │ ║
27
- ║ └─────────────────────────────────────────────────────────────────────┘ ║
28
- ║ ║
29
- ║ ┌─────────────────────────────────────────────────────────────────────┐ ║
30
- ║ │ 👥 GROUPS │ 👤 PROFILE │ 📰 MEDIA │ ║
31
- ║ │ ├─ Get Invite Info │ ├─ checkNumber │ ├─ Newsletter Paths │ ║
32
- ║ │ ├─ Join via Invite │ ├─ setBio │ ├─ Image Upload │ ║
33
- ║ │ ├─ Set Announcement │ ├─ updateName │ ├─ Video Upload │ ║
34
- ║ │ ├─ Set Locked │ ├─ setProfilePic │ ├─ Audio Upload │ ║
35
- ║ │ ├─ Request List │ ├─ removeProfilePic │ ├─ Document Upload │ ║
36
- ║ │ ├─ Approve │ └─ rejectCall │ └─ Sticker Upload │ ║
37
- ║ │ └─ Reject │ │ │ ║
38
- ║ └─────────────────────────────────────────────────────────────────────┘ ║
39
- ║ ║
40
- ║ ✅ No Browser Required ✅ Multi-Device ✅ WebSocket Based ║
41
- ║ ✅ Active Maintenance ✅ MIT License ✅ Full API Coverage ║
42
- ║ ║
43
- ╚═══════════════════════════════════════════════════════════════════════════╝
44
- ```
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" />
45
3
 
46
4
  <br/>
47
5
 
48
- ```
49
- ██╗ ██╗██████╗ █████╗ ███████╗████████╗
50
- ██║ ██║██╔══██╗██╔══██╗██╔════╝╚══██╔══╝
51
- ███████║██████╔╝███████║███████╗ ██║
52
- ██╔══██║██╔══██╗██╔══██║╚════██║ ██║
53
- ██║ ██║██████╔╝██║ ██║███████║ ██║
54
- ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝
6
+ <!-- Rounded + border image -->
7
+ <a href="https://ishanx-pro.site.je">
8
+ <kbd>
9
+ <img src="https://i.postimg.cc/9Q6q2Pv6/IMG-20260925-WA4965.jpg" alt="WhatsApp Baileys 2026" width="720" />
10
+ </kbd>
11
+ </a>
55
12
 
56
- WhatsApp Web API Fork
57
- By Lovely ❤️
58
- ```
13
+ <br/><br/>
59
14
 
60
- <img src="https://i.postimg.cc/9Q6q2Pv6/IMG-20260925-WA4965.jpg" alt="ishumdz-bail" width="700" />
61
15
 
62
- <br/>
16
+ # 🧑‍💻 ishumdz-bail
63
17
 
64
- [![npm](https://img.shields.io/badge/npm-ishumdz--bail-25D366?style=for-the-badge&logo=npm&logoColor=white)](https://www.npmjs.com/package/ishumdz-bail)
65
- [![GitHub](https://img.shields.io/badge/GitHub-lovelyofficial/ishumdz--bail-FF4500?style=for-the-badge&logo=github&logoColor=white)](https://github.com/lovelyofficial/ishumdz-bail)
66
- [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D20-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)](https://nodejs.org)
67
- [![License](https://img.shields.io/badge/License-MIT-blue?style=for-the-badge)](LICENSE)
68
- [![WhatsApp](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://whatsapp.com)
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>
69
30
 
70
31
  **Open-source WhatsApp automation library — no browser required.**
71
32
  Built on WebSocket for speed, stability, and full multi-device support.
72
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
+
73
38
  </div>
74
39
 
75
40
  ---
76
41
 
77
- ## 🚀 Installation
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
78
51
 
79
52
  ```bash
80
53
  npm install ishumdz-bail
81
54
  ```
82
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 text games (Blackjack, Slots, Dice, Coin Flip, Roulette, Mines, Trivia, RPS) + 6 live HTML games (Chess, Tic Tac Toe, Connect Four, 2048, Snake, Memory) playable inside chat |
94
+ | 📞 **VoIP Caller** | Answer incoming calls with audio playback using WASM VoIP engine |
95
+ | ⚡ **Pro Methods** | 34 convenience methods: Polls, Newsletter, Status, Chat, Groups, Profile |
96
+
83
97
  ---
84
98
 
85
- ## ⚡ Quick Start
99
+ ## 📞 VoIP Caller (Call Answer + Audio)
100
+
101
+ Answer incoming WhatsApp calls and play audio automatically:
86
102
 
87
103
  ```javascript
88
- const { makeWASocket, useMultiFileAuthState, attachProMethods } = require('ishumdz-bail');
104
+ const { makeWASocket, enableCallAutoAnswer } = require('ishumdz-bail');
105
+
106
+ const sock = makeWASocket({ auth: state });
89
107
 
90
- const { state, saveCreds } = await useMultiFileAuthState('auth_info');
108
+ // Enable auto-answer with audio playback
109
+ sock.enableCallAutoAnswer({
110
+ audio: './welcome.wav', // Audio file to play (MP3/WAV)
111
+ autoAnswer: true, // Auto-answer incoming calls
112
+ answerDelayMs: 200, // Delay before answering
113
+ durationMs: 60000, // Max call duration (60s)
114
+ loop: true, // Loop audio
115
+ onCall: (call) => {}, // Callback on incoming call
116
+ onAnswer: (call) => {}, // Callback when answered
117
+ onEnd: (call, reason) => {} // Callback when ended
118
+ });
119
+ ```
91
120
 
92
- const sock = makeWASocket({
93
- auth: state,
94
- syncFullHistory: false,
95
- aiLabel: true,
121
+ **Manual call handling:**
122
+ ```javascript
123
+ sock.ev.on('call', async ([call]) => {
124
+ if (call.status === 'offer') {
125
+ // Reject call
126
+ await sock.rejectCall(call.id, call.from);
127
+
128
+ // Or accept with VoIP client
129
+ const voipClient = getActiveVoipClient();
130
+ if (voipClient) {
131
+ const activeCall = voipClient.activeCall;
132
+ activeCall.accept('./audio.wav');
133
+ }
134
+ }
96
135
  });
136
+ ```
97
137
 
98
- attachProMethods(sock);
138
+ ---
99
139
 
100
- sock.ev.on('creds.update', saveCreds);
140
+ ## ⚡ Pro Methods
101
141
 
102
- sock.ev.on('connection.update', ({ connection }) => {
103
- if (connection === 'open') {
104
- console.log('✅ Connected!');
105
- }
142
+ 34 convenience methods attached to socket via `attachProMethods()`:
143
+
144
+ ```javascript
145
+ const { makeWASocket, attachProMethods } = require('ishumdz-bail');
146
+
147
+ const sock = makeWASocket({ auth: state });
148
+ attachProMethods(sock); // Attach all Pro methods
149
+ ```
150
+
151
+ ### 📊 Polls Pro
152
+
153
+ ```javascript
154
+ // Create a poll
155
+ await sock.sendPoll(jid, {
156
+ name: 'What is your favorite color?',
157
+ values: ['Red', 'Blue', 'Green', 'Yellow'],
158
+ selectableCount: 1
159
+ });
160
+
161
+ // Vote on a poll
162
+ await sock.sendPollVote(jid, pollMessage, ['Red']);
163
+
164
+ // Get poll results
165
+ const votes = sock.getAggregatePollVotes(pollMessage);
166
+ ```
167
+
168
+ ### 📢 Newsletter/Channel Pro
169
+
170
+ ```javascript
171
+ // Smart channel poll vote (auto-resolves links, IDs)
172
+ await sock.channelVote('https://whatsapp.com/channel/xxx/123', 1);
173
+
174
+ // React to channel post
175
+ await sock.newsletterReact(channelJid, serverId, '👍');
176
+
177
+ // Get channel messages (decoded)
178
+ const messages = await sock.newsletterGetMessages(channelJid, 50);
179
+
180
+ // Search channels
181
+ const results = await sock.newsletterSearch('technology');
182
+
183
+ // List followed channels
184
+ const channels = await sock.newsletterList();
185
+ ```
186
+
187
+ ### 🟢 Status/Stories Pro
188
+
189
+ ```javascript
190
+ // Send text status
191
+ await sock.sendStatusText('Hello World!', {
192
+ backgroundColor: '#25D366',
193
+ font: 1
194
+ });
195
+
196
+ // Send media status
197
+ await sock.sendStatusMedia('./photo.jpg', {
198
+ type: 'image',
199
+ caption: 'My status!'
106
200
  });
201
+
202
+ // React to status
203
+ await sock.reactStatus(statusKey, '❤️');
204
+ ```
205
+
206
+ ### 💬 Chat Pro
207
+
208
+ ```javascript
209
+ // Edit a message
210
+ await sock.editMessage(jid, messageKey, 'Updated text!');
211
+
212
+ // Delete a message
213
+ await sock.deleteMessage(jid, messageKey);
214
+
215
+ // Pin a message (24h, 7d, or 30d)
216
+ await sock.pinMessage(jid, messageKey, 86400); // 24 hours
217
+
218
+ // Star/unstar a message
219
+ await sock.starMessage(jid, messageKey, true);
220
+
221
+ // React to a message
222
+ await sock.reactMessage(jid, messageKey, '😂');
223
+
224
+ // Send presence (typing indicator)
225
+ await sock.sendPresence(jid, 'composing');
226
+
227
+ // Quick reply with quote
228
+ await sock.reply(jid, 'This is a reply!', quotedMessage);
229
+ ```
230
+
231
+ ### 👥 Groups Pro
232
+
233
+ ```javascript
234
+ // Get group info from invite link
235
+ const info = await sock.groupGetInviteInfo('https://chat.whatsapp.com/xxx');
236
+
237
+ // Join group via invite
238
+ await sock.groupJoinViaInvite('https://chat.whatsapp.com/xxx');
239
+
240
+ // Set announcement mode (admin only)
241
+ await sock.groupSetAnnouncement(groupJid, true);
242
+
243
+ // Set locked mode (admin only)
244
+ await sock.groupSetLocked(groupJid, true);
245
+
246
+ // Manage join requests
247
+ const requests = await sock.groupRequestParticipantsList(groupJid);
248
+ await sock.groupApproveParticipants(groupJid, [participant1, participant2]);
249
+ await sock.groupRejectParticipants(groupJid, [participant3]);
250
+ ```
251
+
252
+ ### 👤 Profile Pro
253
+
254
+ ```javascript
255
+ // Check if number exists on WhatsApp
256
+ const result = await sock.checkNumber('1234567890');
257
+ console.log(result.exists); // true/false
258
+
259
+ // Update bio
260
+ await sock.setBio('Hello, I am a bot!');
261
+
262
+ // Update display name
263
+ await sock.updateProfileName('My Bot');
264
+
265
+ // Set profile picture
266
+ await sock.setProfilePicture(jid, './avatar.jpg');
267
+
268
+ // Remove profile picture
269
+ await sock.removeProfilePicture(jid);
107
270
  ```
108
271
 
109
272
  ---
110
273
 
111
- ## 🎮 Games
274
+ ## 🎮 Built-in Games
275
+
276
+ 8 fun games for your WhatsApp bot:
112
277
 
113
278
  ```javascript
114
279
  const { blackjack, slotMachine, diceGame, coinFlip, roulette, rps, trivia, createMines } = require('ishumdz-bail');
115
280
 
116
- // 🃏 Blackjack
117
- const bj = blackjack('start', [], [], 100);
118
- // bj.playerHand, bj.dealerHand, bj.status
281
+ // Blackjack
282
+ const game = blackjack('start', [], [], 100); // Start with 100 bet
283
+ // game.playerHand, game.dealerHand, game.status
119
284
 
120
- // 🎰 Slots
285
+ // Slots
121
286
  const slots = slotMachine(100);
122
287
  // slots.reels, slots.payout
123
288
 
124
- // 🎲 Dice
125
- const dice = diceGame(100, 'high');
289
+ // Dice
290
+ const dice = diceGame(100, 'high'); // Bet on high (7-12)
126
291
  // dice.total, dice.dice1, dice.dice2
127
292
 
128
- // 🪙 Coin Flip
293
+ // Coin Flip
129
294
  const flip = coinFlip(100, 'heads');
130
295
  // flip.result, flip.payout
131
296
 
132
- // 🎡 Roulette
297
+ // Roulette
133
298
  const spin = roulette(100, 'red');
134
- // spin.number, spin.color
299
+ // spin.number, spin.color, spin.payout
135
300
 
136
- // ✊ Rock Paper Scissors
301
+ // Rock Paper Scissors
137
302
  const game = rps('rock');
138
303
  // game.playerChoice, game.botChoice, game.result
139
304
 
140
- // 🧠 Trivia
141
- const q = trivia(100);
142
- // q.question, q.options, q.answer
305
+ // Trivia
306
+ const question = trivia(100);
307
+ // question.question, question.options, question.answer
143
308
 
144
- // 💣 Mines
145
- const mines = createMines(5, 5, 5);
146
- const tile = revealTile(mines, 0, 0);
147
- const cashout = cashoutMines(mines, 100);
309
+ // Mines
310
+ const mines = createMines(5, 5, 5); // 5x5 grid, 5 mines
311
+ const tile = revealTile(mines, 0, 0); // Reveal tile at (0,0)
312
+ // tile.safe, tile.mine
313
+ const cashout = cashoutMines(mines, 100); // Cash out
314
+ // cashout.payout
148
315
  ```
149
316
 
150
- ---
317
+ ## 💬 Rich Response (GenAI Bubble)
151
318
 
152
- ## 📞 VoIP Caller
319
+ Send messages that render as Meta AI-style bubbles inside WhatsApp. Supports multiple primitives in a single message:
153
320
 
154
321
  ```javascript
155
- const { makeWASocket, enableCallAutoAnswer, getActiveVoipClient } = require('ishumdz-bail');
322
+ // Markdown text
323
+ await sock.sendMessage(jid, {
324
+ richResponse: {
325
+ text: '**Hello** from *ishumdz-bail*',
326
+ responseId: 'optional-uuid'
327
+ }
328
+ })
156
329
 
157
- const sock = makeWASocket({ auth: state });
330
+ // Code block
331
+ await sock.sendMessage(jid, {
332
+ richResponse: {
333
+ code: 'console.log("hello")',
334
+ language: 'javascript'
335
+ }
336
+ })
337
+
338
+ // Table
339
+ await sock.sendMessage(jid, {
340
+ richResponse: {
341
+ table: {
342
+ rows: [
343
+ ['Name', 'Age'],
344
+ ['Alice', '25'],
345
+ ['Bob', '30']
346
+ ]
347
+ }
348
+ }
349
+ })
158
350
 
159
- // Auto-answer calls with audio
160
- sock.enableCallAutoAnswer({
161
- audio: './welcome.wav',
162
- autoAnswer: true,
163
- answerDelayMs: 200,
164
- durationMs: 60000,
165
- loop: true
166
- });
351
+ // HTML (raw HTML rendered in client)
352
+ await sock.sendMessage(jid, {
353
+ richResponse: {
354
+ text: 'fallback',
355
+ html: '<b>bold</b> <a href="https://example.com">link</a>'
356
+ }
357
+ })
167
358
 
168
- // Manual call handling
169
- sock.ev.on('call', async ([call]) => {
170
- if (call.status === 'offer') {
171
- await sock.rejectCall(call.id, call.from);
359
+ // LaTeX
360
+ await sock.sendMessage(jid, {
361
+ richResponse: {
362
+ latex: 'E = mc^2'
172
363
  }
173
- });
364
+ })
365
+
366
+ // Map / location
367
+ await sock.sendMessage(jid, {
368
+ richResponse: {
369
+ map: {
370
+ latitude: -6.2,
371
+ longitude: 106.8,
372
+ zoom: 15,
373
+ title: 'Jakarta',
374
+ annotations: []
375
+ }
376
+ }
377
+ })
378
+
379
+ // Inline image
380
+ await sock.sendMessage(jid, {
381
+ richResponse: {
382
+ imageUrl: 'https://example.com/photo.jpg'
383
+ }
384
+ })
385
+ ```
386
+
387
+ **Shortcut methods** (all accept `quoted` and `options`):
388
+
389
+ ```javascript
390
+ await sock.sendTable(jid, 'Title', ['H1','H2'], [['A','B']], quoted)
391
+ await sock.sendList(jid, 'Title', ['item1','item2'], quoted)
392
+ await sock.sendCodeBlock(jid, 'print("hello")', quoted, { language: 'python' })
393
+ await sock.sendLatex(jid, quoted, { latex: 'x^2 + y^2 = z^2' })
394
+ await sock.sendRichMessage(jid, submessages, quoted)
174
395
  ```
175
396
 
176
397
  ---
177
398
 
178
- ## ⚡ Pro Methods
399
+ ## 🖼️ Album Message
400
+
401
+ Send multiple images/videos grouped into a single WA album:
179
402
 
180
403
  ```javascript
181
- const { makeWASocket, attachProMethods } = require('ishumdz-bail');
404
+ await sock.sendMessage(jid, {
405
+ album: [
406
+ { image: { url: 'https://example.com/a.jpg' } },
407
+ { image: { url: 'https://example.com/b.jpg' }, caption: 'caption foto kedua' },
408
+ { video: { url: 'https://example.com/c.mp4' }, gifPlayback: false }
409
+ ],
410
+ caption: 'caption ini otomatis ke item pertama'
411
+ })
412
+ ```
182
413
 
183
- const sock = makeWASocket({ auth: state });
184
- attachProMethods(sock); // Attach all 34 Pro methods
414
+ ---
415
+
416
+ ## 🚫 Ban Checker
417
+
418
+ 4-factor ban detection against WhatsApp's own servers — no third-party API:
419
+
420
+ ```javascript
421
+ const result = await sock.checkBanStatus('628123456789')
422
+ // or: sock.checkBanStatus('628123456789@s.whatsapp.net')
423
+
424
+ console.log(result)
425
+ // {
426
+ // status: 'ACTIVE' | 'PROFILE_HIDDEN' | 'LIKELY_ACTIVE' | 'BANNED' | 'OFF_WHATSAPP' | 'UNKNOWN',
427
+ // emoji: '🟢' | '🟡' | '🔴' | '❓',
428
+ // confidence: 0..1,
429
+ // deviceCount: number | null,
430
+ // registryExists: boolean | null,
431
+ // pageVisible: boolean | null,
432
+ // profileName: string | null
433
+ // }
185
434
  ```
186
435
 
187
- ### 📊 Polls
436
+ **Four factors checked:**
437
+ - **Factor A** — Live registry (`sock.onWhatsApp`)
438
+ - **Factor B** — Public send-page title/image probe (`api.whatsapp.com`)
439
+ - **Factor C** — Identity-key device probe via USync (strongest: banned numbers have their keys destroyed)
440
+ - **Factor D** — Device-count signature (2+ = ACTIVE, 1 generic = likely BANNED, 0 = BANNED/OFF_WA)
441
+
442
+ ---
443
+
444
+ ## 🆔 Username Socket (w:mex)
445
+
446
+ Full WA `@username` API via WhatsApp's internal Pando/MEX GraphQL protocol, query IDs sourced from Java decompile of WA 2.26.17.2:
188
447
 
189
448
  ```javascript
190
- await sock.sendPoll(jid, { name: 'Vote?', values: ['Yes', 'No'] });
191
- await sock.sendPollVote(jid, pollMsg, ['Yes']);
192
- const votes = sock.getAggregatePollVotes(pollMsg);
449
+ // Check availability
450
+ const res = await sock.checkUsername('myusername')
451
+ // { available: true, username } or { available: false, suggestions: [...] }
452
+
453
+ // Set username
454
+ await sock.setUsername('myusername')
455
+
456
+ // Delete username
457
+ await sock.deleteUsername()
458
+
459
+ // Get your own username
460
+ const mine = await sock.getMyUsername()
461
+
462
+ // Pin/unpin username
463
+ await sock.setUsernamePin(true)
464
+
465
+ // Find user by username
466
+ const user = await sock.findUserByUsername('someuser', pin)
467
+
468
+ // Fetch usernames of your contacts in batch
469
+ const usernames = await sock.fetchContactUsernames('94xxxx@s.whatsapp.net', '628yyy@s.whatsapp.net')
470
+
471
+ // Get username suggestions
472
+ const suggestions = await sock.getUsernameRecommendations()
193
473
  ```
194
474
 
195
- ### 📢 Newsletter/Channels
475
+ ---
476
+
477
+ ## 🏘️ Communities Socket
196
478
 
197
479
  ```javascript
198
- await sock.channelVote('https://whatsapp.com/channel/xxx', 1);
199
- await sock.newsletterReact(jid, serverId, '👍');
200
- const msgs = await sock.newsletterGetMessages(jid, 50);
201
- const results = await sock.newsletterSearch('tech');
202
- const channels = await sock.newsletterList();
480
+ // Create community
481
+ const community = await sock.communityCreate('Community Name', 'Description')
482
+
483
+ // Create group inside community
484
+ await sock.communityCreateGroup('Group Name', [jid1, jid2], communityJid)
485
+
486
+ // Link/unlink existing group
487
+ await sock.communityLinkGroup(groupJid, communityJid)
488
+ await sock.communityUnlinkGroup(groupJid, communityJid)
489
+
490
+ // Fetch linked groups
491
+ const groups = await sock.communityFetchLinkedGroups(communityJid)
492
+
493
+ // Manage participants
494
+ await sock.communityParticipantsUpdate(communityJid, [jid1], 'add') // 'add' | 'remove' | 'promote' | 'demote'
495
+
496
+ // Invite code
497
+ const code = await sock.communityInviteCode(communityJid)
498
+ await sock.communityRevokeInvite(communityJid)
499
+ await sock.communityAcceptInvite(code)
500
+
501
+ // Settings
502
+ await sock.communityToggleEphemeral(communityJid, 86400) // seconds
503
+ await sock.communityMemberAddMode(communityJid, 'admin_add')
504
+ await sock.communityJoinApprovalMode(communityJid, 'on')
505
+ await sock.communityUpdateSubject(communityJid, 'New Name')
506
+ await sock.communityUpdateDescription(communityJid, 'New Desc')
507
+ await sock.communityLeave(communityJid)
508
+ ```
509
+
510
+ ---
511
+
512
+ ## 🔕 noSelfSync
513
+
514
+ Skip syncing outgoing messages to your own linked devices. Useful for high-volume bots where sync traffic is unnecessary:
515
+
516
+ ```javascript
517
+ await sock.sendMessage(jid, { text: 'hello' }, { noSelfSync: true })
518
+
519
+ // Also supported in all shortcut methods:
520
+ await sock.sendTable(jid, title, headers, rows, quoted, { noSelfSync: true })
521
+ await sock.sendCodeBlock(jid, code, quoted, { noSelfSync: true })
203
522
  ```
204
523
 
205
- ### 🟢 Status/Stories
524
+ > **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.
525
+
526
+ ---
527
+
528
+ ## 🔄 Stability & Disconnect Handling
529
+
530
+ ishumdz-bail ships `classifyDisconnect()` — maps every WA status code into an actionable result:
206
531
 
207
532
  ```javascript
208
- await sock.sendStatusText('Hello!', { backgroundColor: '#25D366' });
209
- await sock.sendStatusMedia('./photo.jpg', { type: 'image' });
210
- await sock.reactStatus(key, '❤️');
533
+ import { classifyDisconnect } from 'ishumdz-bail'
534
+
535
+ sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
536
+ if (connection === 'close') {
537
+ const code = lastDisconnect?.error?.output?.statusCode
538
+ const info = classifyDisconnect(code)
539
+
540
+ console.log(info)
541
+ // {
542
+ // category: 'fatal' | 'recoverable' | 'rate-limited' | 'unknown',
543
+ // shouldReconnect: boolean,
544
+ // backoffMs: number, // ms to wait before reconnecting
545
+ // message: string,
546
+ // code: number
547
+ // }
548
+
549
+ if (info.shouldReconnect) {
550
+ setTimeout(() => reconnect(), info.backoffMs)
551
+ }
552
+ }
553
+ })
211
554
  ```
212
555
 
213
- ### 💬 Chat
556
+ **Code map:**
557
+
558
+ | Code | Category | Reconnect | Backoff |
559
+ |---|---|---|---|
560
+ | 401, 440 | fatal | ❌ | — |
561
+ | 515 | recoverable | ✅ | 0 ms (immediate) |
562
+ | 405 | fatal | ❌ | — |
563
+ | 408 | recoverable | ✅ | 30 s |
564
+ | 503 | recoverable | ✅ | 5 min |
565
+ | 429 | rate-limited | ✅ | 60 s |
566
+ | 500 | recoverable | ✅ | 5 s |
567
+ | 503 | recoverable | ✅ | 10 s |
568
+ | Graceful close | recoverable | ✅ | 2 s |
569
+ | Unknown | unknown | ✅ | 15 s |
570
+
571
+ > **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.
572
+
573
+ ---
574
+
575
+ ## ⏱️ Rate Limiter
576
+
577
+ Anti-ban pacing calculator — wire into your send path before each `sendMessage`:
214
578
 
215
579
  ```javascript
216
- await sock.editMessage(jid, key, 'Updated!');
217
- await sock.deleteMessage(jid, key);
218
- await sock.pinMessage(jid, key, 86400);
219
- await sock.starMessage(jid, key, true);
220
- await sock.reactMessage(jid, key, '😂');
221
- await sock.sendPresence(jid, 'composing');
222
- await sock.reply(jid, 'Reply!', quotedMsg);
580
+ import { RateLimiter } from 'ishumdz-bail'
581
+
582
+ const limiter = new RateLimiter({
583
+ maxPerMinute: 8,
584
+ maxPerHour: 200,
585
+ maxPerDay: 1500,
586
+ minDelayMs: 1500,
587
+ maxDelayMs: 5000,
588
+ newChatDelayMs: 3000,
589
+ maxIdenticalMessages: 3,
590
+ burstAllowance: 3
591
+ })
592
+
593
+ async function safeSend(jid, content) {
594
+ const delay = await limiter.getDelay(jid, content)
595
+ if (delay === -1) throw new Error('Rate limit exceeded — blocked')
596
+ if (delay > 0) await new Promise(r => setTimeout(r, delay))
597
+ await sock.sendMessage(jid, content)
598
+ limiter.record(jid, content)
599
+ }
223
600
  ```
224
601
 
225
- ### 👥 Groups
602
+ ---
603
+
604
+ ## 📦 Supported Message Types
605
+
606
+ Every WhatsApp message type is covered:
607
+
608
+ - Text, image, video, audio, document, sticker, GIF/video note (PTV)
609
+ - Location & live location
610
+ - Contact / vCard
611
+ - Poll (create, vote, add option, poll result)
612
+ - Button, list, template, interactive (native flow)
613
+ - Album (multiple media in one message)
614
+ - Event & event invite
615
+ - Group invite, group status, group mention
616
+ - Spoiler (blurred) messages
617
+ - Reaction & edited message
618
+ - View-once media
619
+ - Status/story mention & reply
620
+ - Newsletter / channel messages
621
+ - Payment & payment invite
622
+ - All WhatsApp Business types: product, catalog, order, invoice, business profile
623
+
624
+ <details>
625
+ <summary><b>Example: Album</b></summary>
226
626
 
227
627
  ```javascript
228
- const info = await sock.groupGetInviteInfo('https://chat.whatsapp.com/xxx');
229
- await sock.groupJoinViaInvite('https://chat.whatsapp.com/xxx');
230
- await sock.groupSetAnnouncement(jid, true);
231
- await sock.groupSetLocked(jid, true);
232
- const requests = await sock.groupRequestParticipantsList(jid);
233
- await sock.groupApproveParticipants(jid, [user1]);
234
- await sock.groupRejectParticipants(jid, [user2]);
628
+ await sock.sendMessage(jid, {
629
+ album: [
630
+ { image: { url: 'https://example.com/1.jpg' } },
631
+ { video: { url: 'https://example.com/2.mp4' } }
632
+ ],
633
+ caption: 'Album caption'
634
+ })
235
635
  ```
636
+ </details>
236
637
 
237
- ### 👤 Profile
638
+ <details>
639
+ <summary><b>Example: Poll</b></summary>
238
640
 
239
641
  ```javascript
240
- const check = await sock.checkNumber('1234567890');
241
- await sock.setBio('My bot');
242
- await sock.updateProfileName('Bot Name');
243
- await sock.setProfilePicture(jid, './avatar.jpg');
244
- await sock.removeProfilePicture(jid);
245
- await sock.rejectCall(callId, callFrom);
642
+ await sock.sendMessage(jid, {
643
+ poll: {
644
+ name: 'Poll Title',
645
+ values: ['Option A', 'Option B'],
646
+ selectableCount: 1
647
+ }
648
+ })
649
+ ```
650
+ </details>
651
+
652
+ <details>
653
+ <summary><b>Example: Spoiler</b></summary>
654
+
655
+ ```javascript
656
+ await sock.sendMessage(jid, {
657
+ text: 'Spoiler content',
658
+ spoiler: true
659
+ })
660
+ ```
661
+ </details>
662
+
663
+ <details>
664
+ <summary><b>Example: Event</b></summary>
665
+
666
+ ```javascript
667
+ await sock.sendMessage(jid, {
668
+ eventMessage: {
669
+ name: 'Meeting',
670
+ description: 'Weekly sync',
671
+ location: { degreesLatitude: -6.2, degreesLongitude: 106.8 },
672
+ startTime: Math.floor(Date.now() / 1000) + 3600
673
+ }
674
+ })
246
675
  ```
676
+ </details>
247
677
 
248
678
  ---
249
679
 
250
- ## 📰 Newsletter Media Paths
680
+ ## 🛠️ Additional Methods
251
681
 
252
682
  ```javascript
253
- const { NEWSLETTER_MEDIA_PATH_MAP } = require('ishumdz-bail');
683
+ // Parse incoming extended/special messages
684
+ sock.ev.on('messages.upsert', ({ messages }) => {
685
+ const extended = sock.parseExtendedMessageContent(messages[0].message)
686
+ if (extended) console.log(extended.type, extended.data)
687
+ })
254
688
 
255
- // All paths for channel uploads
256
- console.log(NEWSLETTER_MEDIA_PATH_MAP);
257
- // {
258
- // image: '/newsletter/newsletter-image',
259
- // video: '/newsletter/newsletter-video',
260
- // document: '/newsletter/newsletter-document',
261
- // audio: '/newsletter/newsletter-audio',
262
- // sticker: '/newsletter/newsletter-image',
263
- // gif: '/newsletter/newsletter-gif',
264
- // ptt: '/newsletter/newsletter-ptt',
265
- // ptv: '/newsletter/newsletter-ptv'
266
- // }
689
+ // Business profile
690
+ const profile = await sock.getBusinessProfile(jid)
691
+ await sock.updateBusinessProfile({ description: 'Open 9-5', email: 'hi@example.com', category: 'Retail' })
692
+
693
+ // Get newsletter/channel JID from URL
694
+ await sock.newsletterId('https://whatsapp.com/channel/...')
695
+
696
+ // Refresh media URL for expired messages
697
+ await sock.updateMediaMessage(message)
698
+ ```
699
+
700
+ ---
701
+
702
+ ## 🎮 Games
703
+
704
+ Built-in games for your WhatsApp bot! Import from `ishumdz-bail`:
705
+
706
+ ```javascript
707
+ import {
708
+ blackjack, slotMachine, diceGame,
709
+ coinFlip, roulette, rps, trivia,
710
+ createMines, revealTile, cashoutMines
711
+ } from 'ishumdz-bail'
712
+ ```
713
+
714
+ ### 🕹️ Live HTML Games (playable inside chat!)
715
+
716
+ Send fully interactive games that render as **Meta AI style live HTML cards** inside WhatsApp (GenAI HTML primitive) — board, AI opponent, score tracking, all running client-side in the chat window. English UI.
717
+
718
+ ```javascript
719
+ import {
720
+ sendChess, // ♚ Chess vs AI (minimax)
721
+ sendTicTacToe, // 🎮 Tic Tac Toe vs AI (unbeatable)
722
+ sendConnectFour, // 🔴 Connect Four vs AI (minimax depth 4)
723
+ send2048, // 🔢 2048 swipe puzzle
724
+ sendSnake, // 🐍 Snake (swipe + arrow keys)
725
+ sendMemory, // 🧩 Memory Match (8 emoji pairs)
726
+ sendHtmlGame // ⭐ send ANY custom HTML game
727
+ } from 'ishumdz-bail'
728
+
729
+ // One line each:
730
+ await sendChess(sock, m.chat)
731
+ await sendTicTacToe(sock, m.chat)
732
+ await sendConnectFour(sock, m.chat)
733
+ await send2048(sock, m.chat)
734
+ await sendSnake(sock, m.chat)
735
+ await sendMemory(sock, m.chat)
736
+ ```
737
+
738
+ Bot command example:
739
+
740
+ ```javascript
741
+ const games = {
742
+ chess: sendChess, ttt: sendTicTacToe, c4: sendConnectFour,
743
+ '2048': send2048, snake: sendSnake, memory: sendMemory
744
+ }
745
+
746
+ // inside messages.upsert handler:
747
+ const cmd = text.replace('.', '').toLowerCase()
748
+ if (games[cmd]) await games[cmd](sock, msg.key.remoteJid)
749
+ ```
750
+
751
+ Custom game (your own HTML):
752
+
753
+ ```javascript
754
+ await sendHtmlGame(sock, jid, '<style>...</style><body>...<script>/* your game */</script></body>', '🎯 My Game')
755
+ ```
756
+
757
+ > ℹ️ Requires a WhatsApp client that supports GenAI HTML cards (recent Android/iOS). Older clients and WhatsApp Web will not render the card.
758
+
759
+ ### 🃏 Blackjack
760
+
761
+ ```javascript
762
+ // Start game
763
+ const game = blackjack('start', [], [], 1000)
764
+ await sock.sendMessage(jid, { text: game.message })
765
+
766
+ // Hit (after start)
767
+ const hit = blackjack('hit', game.playerHand, game.dealerHand, 1000)
768
+
769
+ // Stand
770
+ const stand = blackjack('stand', game)
771
+
772
+ // Double
773
+ const dbl = blackjack('double', game)
774
+ ```
775
+
776
+ ### 🎰 Slot Machine
777
+
778
+ ```javascript
779
+ const slot = slotMachine(100)
780
+ await sock.sendMessage(jid, { text: slot.message })
781
+ // 🎰 [🍒] [🍋] [💎] - NO MATCH
782
+ ```
783
+
784
+ ### 🎲 Dice
785
+
786
+ ```javascript
787
+ const dice = diceGame(100, 'high') // high, low, or seven
788
+ await sock.sendMessage(jid, { text: dice.message })
789
+ ```
790
+
791
+ ### 🪙 Coin Flip
792
+
793
+ ```javascript
794
+ const coin = coinFlip(100, 'heads') // heads or tails
795
+ await sock.sendMessage(jid, { text: coin.message })
796
+ ```
797
+
798
+ ### 🎰 Roulette
799
+
800
+ ```javascript
801
+ const rou = roulette(100, 'red') // red, black, odd, even, low, high
802
+ await sock.sendMessage(jid, { text: rou.message })
803
+ ```
804
+
805
+ ### ✊ Rock Paper Scissors
806
+
807
+ ```javascript
808
+ const r = rps('rock') // rock, paper, scissors
809
+ await sock.sendMessage(jid, { text: r.message })
810
+ ```
811
+
812
+ ### 💣 Mines
813
+
814
+ ```javascript
815
+ // Create game
816
+ const game = createMines(5, 5, 5) // rows, cols, mines
817
+
818
+ // Reveal tile
819
+ const result = revealTile(game, 0, 0) // row, col
820
+ await sock.sendMessage(jid, { text: result.message })
821
+
822
+ // Cashout
823
+ const cashout = cashoutMines(game, 100)
824
+ await sock.sendMessage(jid, { text: cashout.message })
825
+ ```
826
+
827
+ ### 🧠 Trivia
828
+
829
+ ```javascript
830
+ const quiz = trivia(100)
831
+ await sock.sendMessage(jid, { text: quiz.message })
832
+
833
+ // Check answer (A, B, C, or D)
834
+ const answer = checkTriviaAnswer('B', quiz.answer, 100)
835
+ await sock.sendMessage(jid, { text: answer.message })
836
+ ```
837
+
838
+ ### 📱 Bot Command Example
839
+
840
+ ```javascript
841
+ sock.ev.on('messages.upsert', async ({ messages }) => {
842
+ const msg = messages[0]
843
+ const text = msg.message?.conversation || ''
844
+
845
+ if (text === '.rps rock' || text === '.rps paper' || text === '.rps scissors') {
846
+ const choice = text.split(' ')[1]
847
+ const result = rps(choice)
848
+ await sock.sendMessage(msg.key.remoteJid, { text: result.message })
849
+ }
850
+
851
+ if (text.startsWith('.slot')) {
852
+ const bet = parseInt(text.split(' ')[1]) || 100
853
+ const result = slotMachine(bet)
854
+ await sock.sendMessage(msg.key.remoteJid, { text: result.message })
855
+ }
856
+
857
+ if (text.startsWith('.coinflip')) {
858
+ const choice = text.split(' ')[1] || 'heads'
859
+ const bet = parseInt(text.split(' ')[2]) || 100
860
+ const result = coinFlip(bet, choice)
861
+ await sock.sendMessage(msg.key.remoteJid, { text: result.message })
862
+ }
863
+ })
267
864
  ```
268
865
 
269
866
  ---
270
867
 
271
- ## 📋 All Features List
272
-
273
- ```
274
- ┌─────────────────────────────────────────────────────────────────────────────┐
275
- │ COMPLETE FEATURE LIST │
276
- ├─────────────────────────────────────────────────────────────────────────────┤
277
- │ │
278
- │ 🎮 GAMES (8 functions) │
279
- │ ├── blackjack(action, playerHand, dealerHand, bet) │
280
- │ ├── slotMachine(bet) │
281
- │ ├── diceGame(bet, prediction) │
282
- │ ├── coinFlip(bet, choice) │
283
- │ ├── roulette(bet, choice) │
284
- │ ├── rps(choice) │
285
- │ ├── trivia(bet) │
286
- │ ├── createMines(rows, cols, mineCount) │
287
- │ ├── revealTile(game, row, col) │
288
- │ └── cashoutMines(game, bet) │
289
- │ │
290
- │ 📞 VOIP (3 functions) │
291
- │ ├── VoipClient │
292
- │ ├── ActiveCall │
293
- │ ├── AudioFeeder │
294
- │ ├── VideoFeeder │
295
- │ ├── enableCallAutoAnswer(sock, options) │
296
- │ └── getActiveVoipClient() │
297
- │ │
298
- │ ⚡ PRO METHODS (34 functions) │
299
- │ ├── sendPoll(jid, pollData) │
300
- │ ├── sendPollVote(jid, pollKey, options) │
301
- │ ├── getAggregatePollVotes(pollMsg) │
302
- │ ├── channelVote(target, option) │
303
- │ ├── newsletterVoteMessage(jid, serverId, option) │
304
- │ ├── newsletterReact(jid, serverId, reaction) │
305
- │ ├── newsletterGetMessages(jid, count) │
306
- │ ├── newsletterSearch(query) │
307
- │ ├── newsletterList() │
308
- │ ├── sendStatusText(text, options) │
309
- │ ├── sendStatusMedia(media, options) │
310
- │ ├── readStatus(key) │
311
- │ ├── reactStatus(key, emoji) │
312
- │ ├── editMessage(jid, key, text) │
313
- │ ├── deleteMessage(jid, key) │
314
- │ ├── pinMessage(jid, key, duration) │
315
- │ ├── unpinMessage(jid, key) │
316
- │ ├── starMessage(jid, key, star) │
317
- │ ├── reactMessage(jid, key, emoji) │
318
- │ ├── sendPresence(jid, presence) │
319
- │ ├── reply(jid, text, quoted) │
320
- │ ├── checkNumber(phone) │
321
- │ ├── setBio(text) │
322
- │ ├── updateProfileName(name) │
323
- │ ├── setProfilePicture(jid, content) │
324
- │ ├── removeProfilePicture(jid) │
325
- │ ├── rejectCall(callId, callFrom) │
326
- │ ├── groupGetInviteInfo(code) │
327
- │ ├── groupJoinViaInvite(code) │
328
- │ ├── groupSetAnnouncement(jid, bool) │
329
- │ ├── groupSetLocked(jid, bool) │
330
- │ ├── groupRequestParticipantsList(jid) │
331
- │ ├── groupApproveParticipants(jid, participants) │
332
- │ ├── groupRejectParticipants(jid, participants) │
333
- │ └── attachProMethods(sock) │
334
- │ │
335
- │ 📰 NEWSLETTER (8 functions) │
336
- │ ├── NEWSLETTER_MEDIA_PATH_MAP │
337
- │ ├── newsletterFetchMessages(jid, count, since, after) │
338
- │ ├── newsletterMetadata(type, query) │
339
- │ ├── newsletterReactMessage(jid, serverId, reaction) │
340
- │ ├── newsletterUpdate(jid, settings) │
341
- │ ├── newsletterCreate(name, description) │
342
- │ ├── newsletterDelete(jid) │
343
- │ └── newsletterFollow(jid) │
344
- │ │
345
- │ 📊 POLL VOTING (1 function) │
346
- │ └── getAggregateVotesInPollMessage(pollMsg) │
347
- │ │
348
- │ 🎯 CORE (10+ functions) │
349
- │ ├── makeWASocket(config) │
350
- │ ├── useMultiFileAuthState(dir) │
351
- │ ├── makeCacheableSignalKeyStore(state, logger) │
352
- │ ├── DisconnectReason │
353
- │ ├── delay(ms) │
354
- │ ├── proto │
355
- │ ├── encodeBinaryNode(frame) │
356
- │ ├── decodeBinaryNode(buffer) │
357
- │ ├── jidDecode(jid) │
358
- │ └── jidEncode(user, server) │
359
- │ │
360
- └─────────────────────────────────────────────────────────────────────────────┘
868
+ ## 📊 Poll Voting
869
+
870
+ Create polls, track votes, and display results.
871
+
872
+ ### 🗳️ Create Poll
873
+
874
+ ```javascript
875
+ await sock.sendMessage(jid, {
876
+ poll: {
877
+ name: 'Best programming language?',
878
+ values: ['JavaScript', 'Python', 'Java', 'Go', 'Rust'],
879
+ selectableCount: 1
880
+ }
881
+ })
882
+ ```
883
+
884
+ ### 📊 Poll with Multiple Selections
885
+
886
+ ```javascript
887
+ await sock.sendMessage(jid, {
888
+ poll: {
889
+ name: 'Which features do you want?',
890
+ values: ['Games', 'AI', 'Stickers', 'Download'],
891
+ selectableCount: 3 // Users can select up to 3 options
892
+ }
893
+ })
894
+ ```
895
+
896
+ ### 📢 Announcement Group Poll (Admin Only Voting)
897
+
898
+ ```javascript
899
+ await sock.sendMessage(groupJid, {
900
+ poll: {
901
+ name: 'Admin Poll',
902
+ values: ['Option 1', 'Option 2'],
903
+ selectableCount: 1,
904
+ toAnnouncementGroup: true
905
+ }
906
+ })
907
+ ```
908
+
909
+ ### 🏆 Poll Result (Fake Results)
910
+
911
+ ```javascript
912
+ await sock.sendMessage(jid, {
913
+ pollResult: {
914
+ name: 'Best framework?',
915
+ votes: [['React', 150], ['Vue', 120], ['Angular', 80]]
916
+ }
917
+ })
918
+ ```
919
+
920
+ ### 📈 Track Poll Votes
921
+
922
+ ```javascript
923
+ import { getAggregateVotesInPollMessage } from 'ishumdz-bail'
924
+
925
+ // Store messages
926
+ const messageStore = new Map()
927
+
928
+ sock.ev.on('messages.upsert', async ({ messages }) => {
929
+ for (const msg of messages) {
930
+ const id = msg.key.remoteJid + ':' + msg.key.id
931
+ messageStore.set(id, msg)
932
+ }
933
+ })
934
+
935
+ // Listen for poll votes
936
+ sock.ev.on('messages.update', async (events) => {
937
+ for (const { key, update } of events) {
938
+ if (update.pollUpdates) {
939
+ const id = key.remoteJid + ':' + key.id
940
+ const pollCreation = messageStore.get(id)
941
+
942
+ if (pollCreation) {
943
+ const votes = getAggregateVotesInPollMessage({
944
+ message: pollCreation,
945
+ pollUpdates: update.pollUpdates
946
+ })
947
+
948
+ console.log('Poll votes:', votes)
949
+ // [{ name: 'Option 1', voters: ['123@s.whatsapp.net'] }, ...]
950
+ }
951
+ }
952
+ }
953
+ })
954
+ ```
955
+
956
+ ### 📱 Poll Bot Command Example
957
+
958
+ ```javascript
959
+ sock.ev.on('messages.upsert', async ({ messages }) => {
960
+ const msg = messages[0]
961
+ const text = msg.message?.conversation || ''
962
+
963
+ // .poll Question | Option1 | Option2 | Option3
964
+ if (text.startsWith('.poll')) {
965
+ const args = text.slice(5).split('|').map(s => s.trim())
966
+ const question = args[0]
967
+ const options = args.slice(1)
968
+
969
+ if (question && options.length >= 2) {
970
+ await sock.sendMessage(msg.key.remoteJid, {
971
+ poll: {
972
+ name: question,
973
+ values: options,
974
+ selectableCount: 1
975
+ }
976
+ })
977
+ }
978
+ }
979
+
980
+ // .pollresult React | 150 | Vue | 120
981
+ if (text.startsWith('.pollresult')) {
982
+ const args = text.slice(12).split('|').map(s => s.trim())
983
+ const votes = []
984
+ for (let i = 0; i < args.length; i += 2) {
985
+ votes.push([args[i], parseInt(args[i + 1]) || 0])
986
+ }
987
+
988
+ await sock.sendMessage(msg.key.remoteJid, {
989
+ pollResult: {
990
+ name: 'Poll Results',
991
+ votes
992
+ }
993
+ })
994
+ }
995
+ })
361
996
  ```
362
997
 
363
998
  ---
364
999
 
365
- ## 📄 License
1000
+ ## 🌐 Community & Support
366
1001
 
367
- MIT License
1002
+ <div align="center">
1003
+
1004
+ <table>
1005
+ <tr>
1006
+ <td align="center">
1007
+ <a href="https://ishanx-pro.site.je">
1008
+ 🌐<br/><b>Website</b><br/>ishanx-pro.site.je
1009
+ </a>
1010
+ </td>
1011
+ <td align="center">
1012
+ <a href="https://shyracore.indevs.in">
1013
+ 💬<br/><b>WhatsApp Channel</b><br/>shyracore.indevs.in
1014
+ </a>
1015
+ </td>
1016
+ </tr>
1017
+ </table>
1018
+
1019
+ **Developer:** Lovely
1020
+
1021
+ </div>
368
1022
 
369
1023
  ---
370
1024
 
371
1025
  <div align="center">
372
1026
 
373
- **Made with ❤️ by Lovely**
1027
+ ### ⭐ If this project helped you, consider giving it a star!
374
1028
 
375
- [![npm](https://img.shields.io/badge/npm-ishumdz--bail-25D366?style=for-the-badge&logo=npm&logoColor=white)](https://www.npmjs.com/package/ishumdz-bail)
376
- [![GitHub](https://img.shields.io/badge/GitHub-lovelyofficial-FF4500?style=for-the-badge&logo=github&logoColor=white)](https://github.com/lovelyofficial/ishumdz-bail)
1029
+ Made with ❤️ by **Lovely**
377
1030
 
378
1031
  </div>
1032
+
1033
+ ---
1034
+
1035
+ ## 📄 License
1036
+
1037
+ MIT
1038
+
1039
+ ---
1040
+
1041
+ ## 📱 Full Feature Overview
1042
+
1043
+ ```
1044
+ ╔═══════════════════════════════════════════════════════════════════════════╗
1045
+ ║ 📱 MAIN FEATURES ║
1046
+ ╠═══════════════════════════════════════════════════════════════════════════╣
1047
+ ║ ║
1048
+ ║ ┌─────────────────────────────────────────────────────────────────────┐ ║
1049
+ ║ │ 🎮 GAMES │ 📞 VOIP CALLER │ ⚡ PRO METHODS │ ║
1050
+ ║ │ ├─ Blackjack │ ├─ Auto Answer │ ├─ sendPoll │ ║
1051
+ ║ │ ├─ Slots │ ├─ Audio Playback │ ├─ sendPollVote │ ║
1052
+ ║ │ ├─ Dice │ └─ VoipClient │ ├─ editMessage │ ║
1053
+ ║ │ ├─ Coin Flip │ │ ├─ deleteMessage │ ║
1054
+ ║ │ ├─ Roulette │ 📊 POLLS │ ├─ pinMessage │ ║
1055
+ ║ │ ├─ Mines │ ├─ Create Poll │ ├─ starMessage │ ║
1056
+ ║ │ ├─ Trivia │ ├─ Vote Poll │ ├─ reactMessage │ ║
1057
+ ║ │ ├─ RPS │ └─ Get Results │ ├─ sendPresence │
1058
+ ║ │ └─ +6 HTML Games │ │ │ ║
1059
+ ║ └─────────────────────────────────────────────────────────────────────┘ ║
1060
+ ║ ║
1061
+ ║ ┌─────────────────────────────────────────────────────────────────────┐ ║
1062
+ ║ │ 📢 NEWSLETTER │ 🟢 STATUS │ 💬 CHAT │ ║
1063
+ ║ │ ├─ channelVote │ ├─ sendText │ ├─ editMessage │ ║
1064
+ ║ │ ├─ newsletterReact │ ├─ sendMedia │ ├─ deleteMessage │ ║
1065
+ ║ │ ├─ getMessages │ ├─ readStatus │ ├─ pinMessage │ ║
1066
+ ║ │ ├─ searchChannels │ └─ reactStatus │ ├─ unpinMessage │ ║
1067
+ ║ │ └─ listChannels │ │ ├─ starMessage │ ║
1068
+ ║ └─────────────────────────────────────────────────────────────────────┘ ║
1069
+ ║ ║
1070
+ ║ ┌─────────────────────────────────────────────────────────────────────┐ ║
1071
+ ║ │ 👥 GROUPS │ 👤 PROFILE │ 📰 MEDIA │ ║
1072
+ ║ │ ├─ Get Invite Info │ ├─ checkNumber │ ├─ Newsletter Paths │ ║
1073
+ ║ │ ├─ Join via Invite │ ├─ setBio │ ├─ Image Upload │ ║
1074
+ ║ │ ├─ Set Announcement │ ├─ updateName │ ├─ Video Upload │ ║
1075
+ ║ │ ├─ Set Locked │ ├─ setProfilePic │ ├─ Audio Upload │ ║
1076
+ ║ │ ├─ Request List │ ├─ removeProfilePic │ ├─ Document Upload │ ║
1077
+ ║ │ ├─ Approve │ └─ rejectCall │ └─ Sticker Upload │ ║
1078
+ ║ │ └─ Reject │ │ │ ║
1079
+ ║ └─────────────────────────────────────────────────────────────────────┘ ║
1080
+ ║ ║
1081
+ ║ ✅ No Browser Required ✅ Multi-Device ✅ WebSocket Based ║
1082
+ ║ ✅ Active Maintenance ✅ MIT License ✅ Full API Coverage ║
1083
+ ║ ║
1084
+ ╚═══════════════════════════════════════════════════════════════════════════╝
1085
+ ```