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 +966 -259
- package/lib/Games/chess.js +92 -0
- package/lib/Games/connect4.js +114 -0
- package/lib/Games/game2048.js +99 -0
- package/lib/Games/htmlGame.js +89 -0
- package/lib/Games/index.js +31 -1
- package/lib/Games/memory.js +82 -0
- package/lib/Games/snake.js +91 -0
- package/lib/Games/tictactoe.js +62 -0
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
16
|
+
# 🧑💻 ishumdz-bail
|
|
63
17
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
##
|
|
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
|
-
##
|
|
99
|
+
## 📞 VoIP Caller (Call Answer + Audio)
|
|
100
|
+
|
|
101
|
+
Answer incoming WhatsApp calls and play audio automatically:
|
|
86
102
|
|
|
87
103
|
```javascript
|
|
88
|
-
const { makeWASocket,
|
|
104
|
+
const { makeWASocket, enableCallAutoAnswer } = require('ishumdz-bail');
|
|
105
|
+
|
|
106
|
+
const sock = makeWASocket({ auth: state });
|
|
89
107
|
|
|
90
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
138
|
+
---
|
|
99
139
|
|
|
100
|
-
|
|
140
|
+
## ⚡ Pro Methods
|
|
101
141
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
//
|
|
117
|
-
const
|
|
118
|
-
//
|
|
281
|
+
// Blackjack
|
|
282
|
+
const game = blackjack('start', [], [], 100); // Start with 100 bet
|
|
283
|
+
// game.playerHand, game.dealerHand, game.status
|
|
119
284
|
|
|
120
|
-
//
|
|
285
|
+
// Slots
|
|
121
286
|
const slots = slotMachine(100);
|
|
122
287
|
// slots.reels, slots.payout
|
|
123
288
|
|
|
124
|
-
//
|
|
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
|
-
//
|
|
293
|
+
// Coin Flip
|
|
129
294
|
const flip = coinFlip(100, 'heads');
|
|
130
295
|
// flip.result, flip.payout
|
|
131
296
|
|
|
132
|
-
//
|
|
297
|
+
// Roulette
|
|
133
298
|
const spin = roulette(100, 'red');
|
|
134
|
-
// spin.number, spin.color
|
|
299
|
+
// spin.number, spin.color, spin.payout
|
|
135
300
|
|
|
136
|
-
//
|
|
301
|
+
// Rock Paper Scissors
|
|
137
302
|
const game = rps('rock');
|
|
138
303
|
// game.playerChoice, game.botChoice, game.result
|
|
139
304
|
|
|
140
|
-
//
|
|
141
|
-
const
|
|
142
|
-
//
|
|
305
|
+
// Trivia
|
|
306
|
+
const question = trivia(100);
|
|
307
|
+
// question.question, question.options, question.answer
|
|
143
308
|
|
|
144
|
-
//
|
|
145
|
-
const mines = createMines(5, 5, 5);
|
|
146
|
-
const tile = revealTile(mines, 0, 0);
|
|
147
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
160
|
-
sock.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
//
|
|
169
|
-
sock.
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
##
|
|
399
|
+
## 🖼️ Album Message
|
|
400
|
+
|
|
401
|
+
Send multiple images/videos grouped into a single WA album:
|
|
179
402
|
|
|
180
403
|
```javascript
|
|
181
|
-
|
|
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
|
-
|
|
184
|
-
|
|
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
|
-
|
|
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
|
-
|
|
191
|
-
await sock.
|
|
192
|
-
|
|
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
|
-
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## 🏘️ Communities Socket
|
|
196
478
|
|
|
197
479
|
```javascript
|
|
198
|
-
|
|
199
|
-
await sock.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
-
|
|
638
|
+
<details>
|
|
639
|
+
<summary><b>Example: Poll</b></summary>
|
|
238
640
|
|
|
239
641
|
```javascript
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
##
|
|
680
|
+
## 🛠️ Additional Methods
|
|
251
681
|
|
|
252
682
|
```javascript
|
|
253
|
-
|
|
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
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
//
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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
|
-
##
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
-
##
|
|
1000
|
+
## 🌐 Community & Support
|
|
366
1001
|
|
|
367
|
-
|
|
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
|
-
|
|
1027
|
+
### ⭐ If this project helped you, consider giving it a star!
|
|
374
1028
|
|
|
375
|
-
|
|
376
|
-
[](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
|
+
```
|