@dark-yasiya/starforge 0.0.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1155 -0
  3. package/lib/adapter/index.js +22 -0
  4. package/lib/adapter/sqlite.js +22 -0
  5. package/lib/addon/index.js +22 -0
  6. package/lib/addon/request.js +22 -0
  7. package/lib/addon/scraper.js +22 -0
  8. package/lib/addon/watcher.js +22 -0
  9. package/lib/constant/arguments.js +22 -0
  10. package/lib/constant/bytes.js +22 -0
  11. package/lib/constant/defaults.js +22 -0
  12. package/lib/constant/errors.js +22 -0
  13. package/lib/constant/index.js +22 -0
  14. package/lib/constant/keywords.js +22 -0
  15. package/lib/constant/patterns.js +22 -0
  16. package/lib/constant/shim.js +22 -0
  17. package/lib/constant/time-strings.js +22 -0
  18. package/lib/constant/types.js +22 -0
  19. package/lib/constant/wa-defaults.js +22 -0
  20. package/lib/index.js +27 -0
  21. package/lib/index.mjs +171 -0
  22. package/lib/message/binaries.js +22 -0
  23. package/lib/message/contents.js +22 -0
  24. package/lib/message/context-info.js +22 -0
  25. package/lib/message/index.js +22 -0
  26. package/lib/message/utils.js +22 -0
  27. package/lib/protocol/detect-bot.js +22 -0
  28. package/lib/protocol/extend-socket.js +22 -0
  29. package/lib/protocol/index.js +22 -0
  30. package/lib/protocol/media-processor.js +22 -0
  31. package/lib/protocol/parse-command.js +22 -0
  32. package/lib/protocol/serialize.js +22 -0
  33. package/lib/util/assertions.js +22 -0
  34. package/lib/util/essentials.js +22 -0
  35. package/lib/util/extras/cache.js +22 -0
  36. package/lib/util/extras/file-type.js +22 -0
  37. package/lib/util/extras/get-file.js +22 -0
  38. package/lib/util/extras/index.js +22 -0
  39. package/lib/util/extras/load-html.js +22 -0
  40. package/lib/util/extras/mutex.js +22 -0
  41. package/lib/util/extras/qr.js +22 -0
  42. package/lib/util/extras/queue.js +22 -0
  43. package/lib/util/extras/semaphore.js +22 -0
  44. package/lib/util/extras/webp-exif.js +22 -0
  45. package/lib/util/extras/zip.js +22 -0
  46. package/lib/util/generics.js +22 -0
  47. package/lib/util/index.js +22 -0
  48. package/lib/util/module.js +22 -0
  49. package/lib/util/runtime.js +22 -0
  50. package/lib/util/validator.js +22 -0
  51. package/package.json +78 -0
package/README.md ADDED
@@ -0,0 +1,1155 @@
1
+ # 🔨 @DarkYasiyaNew/starforge
2
+
3
+ [![Logo](https://files.catbox.moe/wbv9fk.png)](https://www.npmjs.com/package/@dark-yasiya/starforge)
4
+
5
+ <p align="center">
6
+ A toolkit for building WhatsApp bots with .
7
+ <br><br>
8
+ <a href="https://www.npmjs.com/package/@dark-yasiya/starforge">
9
+ <img src="https://img.shields.io/npm/v/@DarkYasiyaNew/starforge?style=for-the-badge&logo=npm"/>
10
+ </a>
11
+ <a href="https://www.npmjs.com/package/@dark-yasiya/starforge">
12
+ <img src="https://img.shields.io/npm/dm/@DarkYasiyaNew/starforge?style=for-the-badge&logo=npm"/>
13
+ </a>
14
+ <a href="https://github.com/DarkYasiyaNew/starforge">
15
+ <img src="https://img.shields.io/github/stars/DarkYasiyaNew/starforge?style=for-the-badge&logo=github"/>
16
+ </a>
17
+ <a href="LICENSE">
18
+ <img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=for-the-badge"/>
19
+ </a>
20
+ <a href="https://nodejs.org">
21
+ <img src="https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&labelColor=green&logoColor=white&style=for-the-badge"/>
22
+ </a>
23
+ <a href="https://bun.sh">
24
+ <img src="https://img.shields.io/badge/bun-%3E%3D1.2-fbf0df?logo=bun&labelColor=14151a&logoColor=white&style=for-the-badge"/>
25
+ </a>
26
+ <a href="#">
27
+ <img src="https://img.shields.io/badge/ESM-only?logo=javascript&labelColor=yellow&logoColor=black&style=for-the-badge"/>
28
+ </a>
29
+ </p>
30
+
31
+ ☕ For donation: [Saweria](https://yasiyamd.lk/DarkYasiyaNew)
32
+
33
+ ### 📋 Table of Content
34
+ - [âš ī¸ Notice](#%EF%B8%8F-notice)
35
+ - [đŸ“Ĩ Installation](#-installation)
36
+ - [🧩 Example](#-example)
37
+ - [📄 Serialized Message](#-serialized-message)
38
+ - [âœ‰ī¸ Sending Message](#%EF%B8%8F-sending-message)
39
+ - [💭 Text](#-text)
40
+ - [😄 Reaction](#-reaction)
41
+ - [📰 Link Preview](#-link-preview)
42
+ - [đŸ–ŧī¸ Media](#%EF%B8%8F-media)
43
+ - [đŸ—’ī¸ Sticker](#%EF%B8%8F-sticker)
44
+ - [👤 Contact](#-contact)
45
+ - [đŸ“Ļ Sticker Pack](#-sticker-pack)
46
+ - [đŸ–ŧī¸ Album](#%EF%B8%8F-album)
47
+ - [📊 Poll](#-poll)
48
+ - [📋 Poll Result](#-poll-result)
49
+ - [đŸ—„ī¸ Interactive](#%EF%B8%8F-interactive)
50
+ - [🎠 Carousel](#-carousel)
51
+ - [🔘 Legacy Button](#-legacy-button)
52
+ - [📋 Legacy List](#-legacy-list)
53
+ - [✨ Rich](#-rich)
54
+ - [â†Šī¸ Copy & Forward](#%EF%B8%8F-copy--forward)
55
+ - [🧰 Additional Options](#-additional-options)
56
+ - 🤖 [AI](#-additional-options)
57
+ - 🕒 [Read Timeout](#-additional-options)
58
+ - đŸ‘Ĩ [Group Status](#-additional-options)
59
+ - đŸ‘ī¸ [Spoiler](#-additional-options)
60
+ - [👤 Chats](#-chats)
61
+ - [rejectCall](#rejectcallcallid-string-callcreatorjid-string)
62
+ - [resolveUserJid](#resolveuserjidjid-string)
63
+ - [updateMemberLabel](#updatememberlabeljid-string-label-string)
64
+ - [setChatEphemeral](#setchatephemeraljid-string-durationsecs-number)
65
+ - [đŸ§ŗ Environments](#-environments)
66
+ - [â¤ī¸ Credits](#%EF%B8%8F-credits)
67
+ - [📄 License](#-license)
68
+
69
+ ### âš ī¸ Notice
70
+
71
+ This project is a toolkit for building WhatsApp bots with and will be used for [@DarkYasiyaNew/starseed](https://github.com/DarkYasiyaNew/starseed#readme).
72
+
73
+ **This library contains no hidden auto-follow code or behavior. It will never automatically follow or subscribe to WhatsApp Channels (Newsletters).**
74
+
75
+ ### đŸ“Ĩ Installation
76
+
77
+ This library follows a user-controlled dependency model. Additional dependencies are not required unless you use the features that rely on them. Install only the dependencies you need.
78
+
79
+ ```bash
80
+ npm install @DarkYasiyaNew/starforge magic-bytes.js qr sharp -js
81
+ ```
82
+
83
+ - `qr` is required by `encodeQR()`.
84
+ - `magic-bytes.js` is used by `detectFileType()`. Alternatively, you can install `file-type`.
85
+ - `sharp` is used for image processing tasks such as generating thumbnails, creating favicons, `createMediaProcessor()`, and more. Alternatively, you can install `@napi-rs/image` or `jimp`. Only one image processing backend is needed.
86
+
87
+ ### 🧩 Example
88
+
89
+ Here's a simple example using .
90
+
91
+ ```javascript
92
+ import { WaClient, createStore } from '-js'
93
+ import { createMediaProcessor, createSerializer, encodeQR, extendSocket } from '@DarkYasiyaNew/starforge'
94
+
95
+ const store = createStore()
96
+ const processor = createMediaProcessor()
97
+
98
+ const client = new WaClient({
99
+ store,
100
+ sessionId: 'main',
101
+ media: { processor }
102
+ })
103
+
104
+ // Extend the client immediately after creating it
105
+ extendSocket(client, {
106
+ // Custom message ID prefix
107
+ messageIdPrefix: 'STARFORGE',
108
+
109
+ // Simulate typing and recording states before sending messages
110
+ simulatePresence: true
111
+ })
112
+
113
+ // Create the serializer
114
+ const serialize = createSerializer(client)
115
+
116
+ client.on('auth_qr', async ({ qr }) => {
117
+ const { ascii, getPngBuffer } = await encodeQR(qr)
118
+ console.log('📷 Scan this QR', ascii)
119
+ })
120
+
121
+ client.on('connection', ({ status }) => {
122
+ if (status !== 'open') return
123
+ console.log('✅ Connected to WhatsApp')
124
+ })
125
+
126
+ client.on('message', async (m) => {
127
+ // The serializer adds several properties to "m"
128
+ m = await serialize(m)
129
+
130
+ if (m.text === 'ping') {
131
+ m.reply('🏓 Pong')
132
+ }
133
+ })
134
+
135
+ await client.connect()
136
+ ```
137
+
138
+ > 📕 Note: `serialize` can also be used with other `message_*` events, such as `message_addon`.
139
+
140
+ ### 📃 Serialized Message
141
+
142
+ The following example shows the serialized message payload.
143
+
144
+ ```javascript
145
+ {
146
+ rawNode: {
147
+ tag: 'message',
148
+ attrs: {
149
+ from: '434311111111111111@lid',
150
+ type: 'text',
151
+ id: 'AC75D8A10E220E8692FC161EBB5FD34A',
152
+ sts: '2792725867333038',
153
+ notify: '‮‮',
154
+ sender_pn: '6287711111111@s.whatsapp.net',
155
+ t: '2792725867'
156
+ },
157
+ content: [ [Object], [Object] ]
158
+ },
159
+ key: {
160
+ remoteJid: '434311111111111111@lid',
161
+ id: 'AC75D8A10E220E8692FC161EBB5FD34A',
162
+ fromMe: false,
163
+ isGroup: false,
164
+ isBroadcast: false,
165
+ isNewsletter: false,
166
+ remoteJidAlt: '6287711111111@s.whatsapp.net',
167
+ senderDevice: 0
168
+ },
169
+ stanzaType: 'text',
170
+ offline: false,
171
+ timestampSeconds: 2792725867,
172
+ expirationSeconds: 86400,
173
+ pushName: '‮‮',
174
+ message: e {
175
+ extendedTextMessage: e {
176
+ endCardTiles: [],
177
+ text: '@DarkYasiyaNew/starforge',
178
+ previewType: 0,
179
+ contextInfo: [e],
180
+ inviteLinkGroupTypeV2: 0
181
+ },
182
+ messageContextInfo: e {
183
+ threadId: [],
184
+ deviceListMetadata: [e],
185
+ deviceListMetadataVersion: 2,
186
+ messageSecret: [Uint8Array]
187
+ }
188
+ },
189
+ id: 'AC75D8A10E220E8692FC161EBB5FD34A',
190
+ chat: '6287711111111@s.whatsapp.net',
191
+ sender: '6287711111111@s.whatsapp.net',
192
+ senderLid: '434311111111111111@lid',
193
+ device: 'android',
194
+ fromMe: false,
195
+ isGroup: false,
196
+ isPrivate: true,
197
+ isBroadcast: false,
198
+ isNewsletter: false,
199
+ isMedia: false,
200
+ msgType: 'extendedTextMessage',
201
+ msg: e {
202
+ endCardTiles: [],
203
+ text: '@DarkYasiyaNew/starforge',
204
+ previewType: 0,
205
+ contextInfo: e {
206
+ mentionedJid: [],
207
+ groupMentions: [],
208
+ statusAttributions: [],
209
+ stanzaId: 'ACF49F7488D66F81B72BD31FDB4A7ADD',
210
+ participant: '434311111111111111@lid',
211
+ quotedMessage: [e],
212
+ expiration: 86400,
213
+ ephemeralSettingTimestamp: [n],
214
+ disappearingMode: [e],
215
+ quotedType: 0
216
+ },
217
+ inviteLinkGroupTypeV2: 0
218
+ },
219
+ quoted: e {
220
+ interactiveAnnotations: [],
221
+ scanLengths: [],
222
+ annotations: [],
223
+ url: 'https://mmg.whatsapp.net/v/t62.7118-24/...',
224
+ mimetype: 'image/jpeg',
225
+ fileSha256: Uint8Array(32) [ 156, 238, ... ],
226
+ fileLength: n { low: 357606, high: 0, unsigned: true },
227
+ height: 1458,
228
+ width: 1220,
229
+ mediaKey: Uint8Array(32) [ 249, 219, ... ],
230
+ fileEncSha256: Uint8Array(32) [ 19, 147, ... ],
231
+ directPath: '/v/t62.7118-24/...',
232
+ mediaKeyTimestamp: n { low: 2792725790, high: 0, unsigned: false },
233
+ jpegThumbnail: Uint8Array(619) [ 255, 216, ... ],
234
+ contextInfo: e {
235
+ mentionedJid: [],
236
+ groupMentions: [],
237
+ statusAttributions: [Array],
238
+ pairedMediaType: 0,
239
+ statusSourceType: 0,
240
+ statusAudienceMetadata: [e],
241
+ mediaDomainInfo: [e]
242
+ },
243
+ id: 'ACF49F7488D66F81B72BD31FDB4A7ADD',
244
+ chat: '6287711111111@s.whatsapp.net',
245
+ sender: '6287711111111@s.whatsapp.net',
246
+ senderLid: '434311111111111111@lid',
247
+ device: 'android',
248
+ fromMe: false,
249
+ isGroup: false,
250
+ isPrivate: true,
251
+ isBroadcast: false,
252
+ isNewsletter: false,
253
+ isMedia: true,
254
+ msgType: 'imageMessage',
255
+ text: '',
256
+ expiration: 86400,
257
+ mentionedJid: [],
258
+ fakeObj: { key: [Object], message: [Object] },
259
+ reply: [AsyncFunction: replyMessage],
260
+ react: [AsyncFunction: reactMessage],
261
+ getProfilePicture: [AsyncFunction: getProfilePicture],
262
+ download: [AsyncFunction: downloadBytes],
263
+ downloadFile: [AsyncFunction: downloadFile]
264
+ },
265
+ expiration: 86400,
266
+ mentionedJid: [],
267
+ text: '@DarkYasiyaNew/starforge',
268
+ reply: [AsyncFunction (anonymous)],
269
+ react: [AsyncFunction: reactMessage],
270
+ getProfilePicture: [AsyncFunction: getProfilePicture]
271
+ }
272
+ ```
273
+
274
+ ### âœ‰ī¸ Sending Message
275
+
276
+ > 📕 Note: You must call `extendSocket(client)` before using any of the following functions.
277
+
278
+ #### 💭 Text
279
+
280
+ `sendText(jid: string, rawText: string, quote?: object, extraContent?: object, options?: object)`
281
+
282
+ ```javascript
283
+ client.sendText(jid, 'Hello 👋đŸģ', m)
284
+
285
+ // Send as view once
286
+ client.sendText(jid, 'Hello 👋đŸģ', m, {
287
+ viewOnce: true
288
+ })
289
+
290
+ // Send as a regular status
291
+ client.sendText([jid, lid], 'Hello 👋đŸģ')
292
+
293
+ // Send as a group status with a custom font color, background color, and font style
294
+ client.sendText(jid, 'Hello 👋đŸģ', null, {
295
+ // RGB: 230, 230, 250
296
+ fontColor: '#E6E6FA',
297
+
298
+ // RGB: 75, 0, 130
299
+ backgroundColor: '#4B0082',
300
+
301
+ // MORNINGBREEZE_REGULAR
302
+ fontType: 7
303
+ }, {
304
+ groupStatus: true
305
+ })
306
+
307
+ // Send with a spoiler, hiding the content between || pipes
308
+ // (currently not all WhatsApp versions render it)
309
+ client.sendText(m.chat, 'đŸ—„ī¸ Secret Password: ||*4640*||', m)
310
+ ```
311
+
312
+ #### 😄 Reaction
313
+
314
+ `sendReact(jid: string, rawEmoji: string, target?: object, options?: object)`
315
+
316
+ ```javascript
317
+ client.sendReact(jid, 'đŸĢĒ', m.key)
318
+
319
+ // You can also react to a group status
320
+ client.sendReact(jid, 'đŸĢĒ', m.key, { groupStatus: true })
321
+ ```
322
+
323
+ #### 📰 Link Preview
324
+
325
+ `sendAdText(jid: string, rawText: string, quote?: object, extraContent?: object, options?: object)`
326
+
327
+ ```javascript
328
+ // Simple and basic usage
329
+ client.sendAdText(jid, 'A tiny discovery ✨', m, {
330
+ title: 'Interesting Article!',
331
+ description: 'See more...',
332
+ thumbnail: /* Buffer | string | Readable */
333
+ })
334
+
335
+ client.sendAdText(jid, 'Something worth reading 📖', m, {
336
+ title: 'Interesting Article!',
337
+ description: 'See more...',
338
+ thumbnail: /* Buffer | string | Readable */,
339
+
340
+ // Custom thumbnail URL
341
+ thumbnailUrl: 'https://www.npmjs.com/package/@dark-yasiya/starforge',
342
+
343
+ // Custom favicon image
344
+ favicon: /* Buffer | string | Readable */,
345
+
346
+ // Render a large, high quality thumbnail
347
+ largeThumbnail: true,
348
+ width: 1920,
349
+ height: 1080
350
+ })
351
+
352
+ // Send as a group status
353
+ client.sendAdText(jid, 'Fresh from the digital garden đŸŒŋ', null, {
354
+ title: 'Interesting Article!',
355
+ description: 'See more...',
356
+ thumbnail: /* Buffer | string | Readable */,
357
+
358
+ // RGB: 255, 214, 102
359
+ fontColor: '#FFD666',
360
+
361
+ // RGB: 24, 18, 43
362
+ backgroundColor: '#18122B',
363
+
364
+ // MORNINGBREEZE_REGULAR
365
+ fontType: 7
366
+ }, {
367
+ groupStatus: true
368
+ })
369
+ ```
370
+
371
+ #### đŸ–ŧī¸ Media
372
+
373
+ `sendMedia(jid: string, source: Buffer | string | Readable, rawText: string, quote?: object, extraContent?: object, options?: object)`
374
+
375
+ ```javascript
376
+ client.sendMedia(jid, 'https://files.catbox.moe/jtofzb.jpeg', '🍂', m)
377
+
378
+ // Send video as Motion Photo (a.k.a. Photo Live)
379
+ client.sendMedia(jid, 'https://path-to-video.mp4/', 'đŸ“Ŋī¸ Motion Photo a.k.a. Photo Live', m, {
380
+ motionThumbnail: 'https://path-to-image.jpg'
381
+ })
382
+
383
+ client.sendMedia(jid, 'https://files.catbox.moe/jtofzb.jpeg', '🍂', m, {
384
+ // Force the media type
385
+ document: true,
386
+ audio: false,
387
+ ptt: false,
388
+ ptv: false,
389
+ sticker: false,
390
+ gifPlayback: false,
391
+
392
+ // Additional payload
393
+ fileName: 'Nature.jpeg',
394
+ mimetype: 'image/jpeg'
395
+ })
396
+
397
+ // Send as a regular status with Close Friends
398
+ client.sendMedia([jid, lid], 'https://files.catbox.moe/jtofzb.jpeg', '🍂', null, null, {
399
+ closeFriends: {
400
+ name: 'To My Friends!',
401
+ emoji: '🍅'
402
+ }
403
+ })
404
+
405
+ // Send as a group status with Close Friends
406
+ // Works with images, videos, and audio
407
+ client.sendMedia(jid, 'https://files.catbox.moe/jtofzb.jpeg', '🍂', null, null, {
408
+ groupStatus: true,
409
+ closeFriends: {
410
+ name: 'To My Friends!',
411
+ emoji: '🍅'
412
+ }
413
+ })
414
+ ```
415
+
416
+ #### đŸ—’ī¸ Sticker
417
+
418
+ `sendSticker(jid: string, source: Buffer | string | Readable, quote?: object, extraContent?: object, options?: object)`
419
+
420
+ ```javascript
421
+ client.sendSticker(jid, 'https://files.catbox.moe/jtofzb.jpeg', m)
422
+
423
+ client.sendSticker(jid, 'https://files.catbox.moe/jtofzb.jpeg', m, {
424
+ // Add custom sticker metadata
425
+ isAiSticker: true,
426
+ premium: 0,
427
+
428
+ // Modify EXIF without external WebP dependencies
429
+ name: '@DarkYasiyaNew/starforge',
430
+ publisher: 'Stellar'
431
+ })
432
+ ```
433
+
434
+ #### 👤 Contact
435
+
436
+ `sendContact(jid: string, contacts: object[], quote?: object, options?: object)`
437
+
438
+ ```javascript
439
+ client.sendContact(jid, [{
440
+ name: 'James J. Jonah',
441
+ org: 'Daily Bugle',
442
+ email: 'james.jonah@example.com',
443
+ website: 'https://example.com',
444
+ location: 'New York, USA',
445
+ other: '',
446
+ number: '155512345678'
447
+ }], m)
448
+
449
+ // You can also send multiple contacts at once
450
+ client.sendContact(jid, [{
451
+ name: 'James J. Jonah',
452
+ org: 'Daily Bugle',
453
+ email: 'james.jonah@example.com',
454
+ website: 'https://example.com',
455
+ location: 'New York, USA',
456
+ other: '',
457
+ number: '155512345678'
458
+ }, {
459
+ name: 'Peter Parker',
460
+ org: 'Freelance Photographer',
461
+ email: 'peter.parker@example.com',
462
+ website: '',
463
+ location: 'New York, USA',
464
+ other: '',
465
+ number: '155598765432'
466
+ }], m)
467
+ ```
468
+
469
+ #### đŸ“Ļ Sticker Pack
470
+
471
+ `sendStickerPack(jid: string, sources: (Buffer | string | Readable)[], quote?: object, extraContent?: object, options?: object)`
472
+
473
+ ```javascript
474
+ client.sendStickerPack(jid, [
475
+ 'https://files.catbox.moe/jtofzb.jpeg',
476
+ 'https://files.catbox.moe/jtofzb.jpeg'
477
+ ], m, {
478
+ name: 'My Sticker Pack đŸ“Ļ',
479
+ publisher: 'Stellar',
480
+ description: 'Limited Sticker!'
481
+ })
482
+ ```
483
+
484
+ #### đŸ–ŧī¸ Album
485
+
486
+ `sendAlbum(jid: string, sources: object[], quote?: object, options?: object)`
487
+
488
+ ```javascript
489
+ client.sendAlbum(jid, [{
490
+ media: /* Buffer | string | Readable */,
491
+ caption: '🌱 Media #1'
492
+ }, {
493
+ media: /* Buffer | string | Readable */,
494
+ caption: '🌱 Media #2'
495
+ }], m)
496
+
497
+ // Send videos as Motion Photos
498
+ // "sendAlbum()" uses the same motion thumbnail input format as "sendMedia()"
499
+ client.sendAlbum(jid, [{
500
+ media: /* Buffer | string | Readable */,
501
+ motionThumbnail: /* Buffer | string | Readable */,
502
+ caption: 'đŸ“Ŋī¸ w/Motion Photo #1'
503
+ }, {
504
+ media: /* Buffer | string | Readable */,
505
+ motionThumbnail: /* Buffer | string | Readable */,
506
+ caption: 'đŸ“Ŋī¸ w/Motion Photo #2'
507
+ }], m)
508
+ ```
509
+
510
+ #### 📊 Poll
511
+
512
+ `sendPoll(jid: string, rawText: string, selections: string[] | object[], quote?: object, extraContent?: object, options?: object)`
513
+
514
+ ```javascript
515
+ client.sendPoll(jid, '📊 Choose your favorite language', [
516
+ 'JavaScript',
517
+ 'Python',
518
+ 'Rust'
519
+ ], m, {
520
+ announcementGroup: false,
521
+ multiSelect: false,
522
+ hideVoter: true,
523
+ endTime: Date.now() + 86_400_000,
524
+ canAddOption: false
525
+ })
526
+ ```
527
+
528
+ #### 📋 Poll Result
529
+
530
+ `sendPollResult(jid: string, rawText: string, selections: string[] | object[], quote?: object, options?: object)`
531
+
532
+ ```javascript
533
+ client.sendPollResult(jid, '📋 Poll Results', [{
534
+ name: 'JavaScript',
535
+ count: 20
536
+ }, {
537
+ name: 'Python',
538
+ count: 18
539
+ }, {
540
+ name: 'Rust',
541
+ count: 22
542
+ }], m)
543
+ ```
544
+
545
+ #### đŸ—„ī¸ Interactive
546
+
547
+ `sendInteractive(jid: string, rawButtons?: object[], quote?: object, extraContent?: object, options?: object)`
548
+
549
+ ```javascript
550
+ const EXAMPLE_BUTTONS = [{
551
+ text: '👉đŸģ Click Me',
552
+ id: 'command_id',
553
+
554
+ // You can add "icon" to each button to use a custom button icon
555
+ icon: 'DEFAULT'
556
+ }, {
557
+ text: '📃 Copy Code',
558
+ copy: '@DarkYasiyaNew/starforge'
559
+ }, {
560
+ text: '🌐 Open URL',
561
+ url: 'https://www.npmjs.com/package/@dark-yasiya/starforge',
562
+
563
+ // More optional options for "cta_url"
564
+ merchantUrl: '',
565
+ canonicalUrl: '',
566
+ landingPageUrl: '',
567
+ isPaymentPreview: false,
568
+ useWebviewPresentation: 'full',
569
+ useWebview: true
570
+ }, {
571
+ text: '📞 Call',
572
+ call: '94743548986'
573
+ }, {
574
+ title: '👉đŸģ Tap Here',
575
+ sections: [{
576
+ title: '🧩 Interesting Menu',
577
+ highlight_label: 'Popular',
578
+ rows: [{
579
+ header: '',
580
+ title: 'â‰ī¸ Coupon',
581
+ description: '',
582
+ id: 'free_coupon_id'
583
+ }]
584
+ }]
585
+ }, {
586
+ // Add custom buttons
587
+ name: 'cta_reminder',
588
+ paramsJson: {},
589
+ icon: 'DOCUMENT'
590
+ }]
591
+
592
+ client.sendInteractive(jid, EXAMPLE_BUTTONS, m, {
593
+ text: 'đŸ—„ī¸ Interactive Message',
594
+ footer: '@DarkYasiyaNew/starforge'
595
+ })
596
+
597
+ // Send with a media header
598
+ client.sendInteractive(jid, EXAMPLE_BUTTONS, m, {
599
+ media: /* Buffer | string | Readable */,
600
+ text: 'đŸ—„ī¸ Interactive Message'
601
+ })
602
+
603
+ // Send with a location header
604
+ client.sendInteractive(jid, EXAMPLE_BUTTONS, m, {
605
+ location: {
606
+ name: '📍 Location Header',
607
+ address: '@DarkYasiyaNew/starforge'
608
+ },
609
+ media: /* Buffer | string | Readable */,
610
+ text: 'đŸ—„ī¸ Interactive Message'
611
+ })
612
+
613
+ // Send with a product header
614
+ client.sendInteractive(jid, EXAMPLE_BUTTONS, m, {
615
+ product: {
616
+ title: '🛒 Product Header',
617
+ businessOwnerJid: '94743548986@s.whatsapp.net'
618
+ },
619
+ media: /* Buffer | string | Readable */,
620
+ text: 'đŸ—„ī¸ Interactive Message'
621
+ })
622
+
623
+ // Additional options
624
+ client.sendInteractive(jid, EXAMPLE_BUTTONS, m, {
625
+ media: /* Buffer | string | Readable */,
626
+ title: '✨ Using Various Options',
627
+
628
+ // Classic footer text
629
+ text: 'đŸ—„ī¸ Interactive Message',
630
+
631
+ // Audio footer
632
+ // (currently iOS only & not all WhatsApp versions render it)
633
+ audioFooter: /* Buffer | string | Readable */,
634
+
635
+ // Force header type
636
+ document: false,
637
+ location: false,
638
+ product: false,
639
+
640
+ // Wrap all buttons in a single option
641
+ optionText: '👉đŸģ Tap Here',
642
+ optionTitle: '🧩 Wrapped Buttons',
643
+
644
+ // Limited time offer
645
+ offerText: '🔖 Limited Time Offer',
646
+ offerCode: '@DarkYasiyaNew/starforge',
647
+ offerUrl: 'https://www.npmjs.com/package/@dark-yasiya/starforge',
648
+ offerExpiration: Date.now() + 86_400_000
649
+ })
650
+ ```
651
+
652
+ #### 🎠 Carousel
653
+
654
+ `sendCarousel(jid: string, rawCards: object[], quote?: object, extraContent?: object, options?: object)`
655
+
656
+ ```javascript
657
+ const EXAMPLE_BUTTONS = [{
658
+ text: '🛒 Check Out!',
659
+ url: 'https://www.npmjs.com/package/@dark-yasiya/starforge',
660
+ icon: 'DEFAULT'
661
+ }, {
662
+ text: '📞 Call Us',
663
+ call: '94743548986'
664
+ }]
665
+
666
+ const CARDS = [{
667
+ // Media is required for carousel cards
668
+ media: /* Buffer | string | Readable */,
669
+
670
+ text: 'Card #1',
671
+
672
+ // Optional
673
+ buttons: EXAMPLE_BUTTONS
674
+ }, {
675
+ media: /* Buffer | string | Readable */,
676
+ title: '✨ Using Various Options',
677
+ text: 'Card #2',
678
+
679
+ // Classic footer text
680
+ footer: '@DarkYasiyaNew/starforge',
681
+
682
+ // Audio footer
683
+ // (currently iOS only & not all WhatsApp versions render it)
684
+ audioFooter: /* Buffer | string | Readable */,
685
+
686
+ // Force header type, carousel cards cannot use document or location headers
687
+ product: false,
688
+
689
+ // Wrap all buttons in a single option
690
+ optionText: '👉đŸģ Tap Here',
691
+ optionTitle: '🧩 Wrapped Buttons',
692
+
693
+ // Limited time offer
694
+ offerText: '🔖 Limited Time Offer',
695
+ offerCode: '@DarkYasiyaNew/starforge',
696
+ offerUrl: 'https://www.npmjs.com/package/@dark-yasiya/starforge',
697
+ offerExpiration: Date.now() + 86_400_000,
698
+
699
+ buttons: EXAMPLE_BUTTONS
700
+ }]
701
+
702
+ client.sendCarousel(jid, CARDS, m, {
703
+ text: '🎠 Carousel Message',
704
+ footer: 'TESTING!'
705
+ })
706
+ ```
707
+
708
+ #### 🔘 Legacy Button
709
+
710
+ `sendLegacyButton(jid: string, rawButtons: object[], quote?: object, extraContent?: object, options?: object)`
711
+
712
+ ```javascript
713
+ // Regular buttons message
714
+ client.sendLegacyButton(jid, [{
715
+ text: '👋đŸģ SignUp',
716
+ id: '#SignUp'
717
+ }], m, {
718
+ // Optional, change to "true" if want proper render on WhatsApp iOS
719
+ viewOnce: false,
720
+
721
+ text: '👆đŸģ Buttons!',
722
+ footer: '@DarkYasiyaNew/starforge',
723
+ })
724
+
725
+ const EXAMPLE_BUTTONS = [{
726
+ text: '👋đŸģ Rating',
727
+ id: '#Rating'
728
+ }, {
729
+ text: '📋 Select',
730
+
731
+ // Force the button to use RESPONSE
732
+ // instead of NATIVE_FLOW (required when using a location header)
733
+ // type: 1,
734
+
735
+ sections: [{
736
+ title: '✨ Section 1',
737
+ rows: [{
738
+ header: '',
739
+ title: '💭 Secret Ingredient',
740
+ description: '',
741
+ id: '#SecretIngredient'
742
+ }]
743
+ }, {
744
+ title: '✨ Section 2',
745
+ highlight_label: 'đŸ”Ĩ Popular',
746
+ rows: [{
747
+ header: '',
748
+ title: 'đŸˇī¸ Coupon',
749
+ description: '',
750
+ id: '#CouponCode'
751
+ }]
752
+ }]
753
+ }]
754
+
755
+ // Buttons with Media & List
756
+ client.sendLegacyButton(jid, EXAMPLE_BUTTONS, m, {
757
+ media: /* Buffer | string | Readable */,
758
+ text: '👆đŸģ Buttons and List!',
759
+ footer: '@DarkYasiyaNew/starforge'
760
+ })
761
+
762
+ // Buttons with the legacy button style
763
+ client.sendLegacyButton(jid, EXAMPLE_BUTTONS, m, {
764
+ location: {
765
+ name: '📍 Location Header',
766
+ address: '@DarkYasiyaNew/starforge'
767
+ },
768
+ media: /* Buffer | string | Readable */,
769
+ text: '👆đŸģ Old Buttons and List!',
770
+ footer: '@DarkYasiyaNew/starforge'
771
+ })
772
+ ```
773
+
774
+ #### 📋 Legacy List
775
+
776
+ `sendLegacyList(jid: string, rawSections: object[], quote?: object, extraContent?: object, options?: object)`
777
+
778
+ ```javascript
779
+ // Regular list message
780
+ client.sendLegacyList(jid, [{
781
+ title: '🚀 Menu 1',
782
+ rows: [{
783
+ title: '✨ AI',
784
+ description: '',
785
+ id: '#AI'
786
+ }]
787
+ }, {
788
+ title: '🌱 Menu 2',
789
+ rows: [{
790
+ title: '🔍 Search',
791
+ description: '',
792
+ id: '#Search'
793
+ }]
794
+ }], m, {
795
+ text: '📋 List!',
796
+ footer: '@DarkYasiyaNew/starforge',
797
+ buttonText: '📋 Select',
798
+ title: '👋đŸģ Hello'
799
+ })
800
+
801
+ // Product list message
802
+ client.sendLegacyList(jid, [{
803
+ title: '🚀 Menu 1',
804
+ products: [{
805
+ productId: '607964531532'
806
+ }, {
807
+ productId: '506965808593'
808
+ }]
809
+ }, {
810
+ title: '🌱 Menu 2',
811
+ products: [{
812
+ productId: '676909529293'
813
+ }, {
814
+ productId: '656988410262'
815
+ }]
816
+ }], m, {
817
+ header: {
818
+ productId: '656988410262',
819
+ thumbnail: /* Buffer | ArrayBufferLike */,
820
+ businessOwnerJid: '434311111111111111@lid'
821
+ },
822
+ text: '📋 List!',
823
+ footer: '@DarkYasiyaNew/starforge',
824
+ buttonText: '📋 Select',
825
+ title: '👋đŸģ Hello'
826
+ })
827
+ ```
828
+
829
+ #### ✨ Rich
830
+
831
+ `sendRich(jid: string, rawSections: string | object[], quote?: object, extraContent?: object, options?: object)`
832
+
833
+ ```javascript
834
+ const EXAMPLE_TEXT = `
835
+ Here's a table comparing grapes and bananas:
836
+
837
+ | **Characteristic** | **Grapes** | **Banana** |
838
+ | --- | --- | --- |
839
+ | **Type** | Fruit, berry | Fruit, large herbaceous plant |
840
+ | **Color** | Purple, red, or green | Yellow or green |
841
+ | **Taste** | Sweet and slightly tart | Sweet and creamy |
842
+ `
843
+
844
+ client.sendRich(jid, EXAMPLE_TEXT, m)
845
+
846
+ // More advanced rich message types
847
+ client.sendRich(jid, [{
848
+ text: '# 🔨 @DarkYasiyaNew/starforge\n\n---\n',
849
+ }, {
850
+ labels: [{
851
+ text: '🔨 Starforge',
852
+ type: 'NEGATIVE'
853
+ }, {
854
+ text: '⚡ ',
855
+ type: 'POSITIVE'
856
+ }, {
857
+ text: 'đŸ“Ļ Modular',
858
+ type: 'NEUTRAL'
859
+ }]
860
+ }, {
861
+ language: 'javascript',
862
+ code: `console.log("Hello World")`
863
+ }, {
864
+ title: 'The Table',
865
+ table: [{
866
+ isHeading: true,
867
+ items: ['', 'Node.js', 'Bun', 'Deno']
868
+ }, {
869
+ isHeading: false,
870
+ items: ['Engine', 'V8 (C++)', 'JavaScriptCore (C++)', 'V8 (C++)']
871
+ }, {
872
+ isHeading: false,
873
+ items: ['Performance', '4/5', '5/5', '4/5']
874
+ }]
875
+ }, {
876
+ extWidget: [{
877
+ title: '📋 Section 1',
878
+ buttons: ['menu', 'label', 'infos']
879
+ }, {
880
+ title: '📄 Section 2',
881
+ buttons: ['gif', 'runtime', 'order']
882
+ }],
883
+ canScroll: false
884
+ }, {
885
+ // When adding an HTML primitive, set "disableEdit" to true if it causes lag or device stuttering
886
+ htmlPayload: `<h1>🔨 @DarkYasiyaNew/starforge</h1><p>A Baileys wrapper designed to make WhatsApp bot development simpler, cleaner, and more flexible.</p>`,
887
+ trustedSources: ['https://github.com/DarkYasiyaNew/starforge']
888
+ }, {
889
+ video: 'https://path-to-video.com/',
890
+ thumbnailUrl: 'https://path-to-tiny-image.com/',
891
+ mime: 'video/mp4',
892
+ fileLength: 13_603,
893
+ duration: 60
894
+ }, {
895
+ image: 'https://path-to-image.com/',
896
+ mime: 'image/jpeg'
897
+ }, {
898
+ imagine: 'https://path-to-image.com/',
899
+ mime: 'image/jpeg'
900
+ }, {
901
+ reels: [{
902
+ reelUrl: 'https://path-to-web.com/',
903
+ thumbnailUrl: 'https://path-to-image.com/',
904
+ creator: 'Dark Yasiya',
905
+ avatarUrl: 'https://path-to-tiny-image.com/',
906
+ title: 'Simple Helper',
907
+ likesCount: 1,
908
+ sharesCount: 1,
909
+ viewCount: 1,
910
+ source: 'https://path-to-web.com/',
911
+ isVerified: true
912
+ }]
913
+ }, {
914
+ posts: [{
915
+ caption: 'A Helper',
916
+ title: '',
917
+ subtitle: '',
918
+ creator: 'Dark Yasiya',
919
+ avatarUrl: 'https://path-to-tiny-image.com/',
920
+ thumbnailUrl: 'https://path-to-image.com/',
921
+ likesCount: 1,
922
+ commentsCount: 1,
923
+ sharesCount: 1,
924
+ postUrl: 'https://path-to-web.com/',
925
+ deepLink: '',
926
+ footerLabel: '',
927
+ footerIcon: '',
928
+ sourceApp: 'FACEBOOK',
929
+ orientation: 'LANDSCAPE',
930
+ type: 'IMAGE',
931
+ isVerified: true,
932
+ isCarousel: false
933
+ }]
934
+ }, {
935
+ title: 'Starseed Premium Script',
936
+ brand: 'Starseed',
937
+ price: 'Rp 150.000',
938
+ salePrice: 'Rp 75.000',
939
+ productUrl: 'https://path-to-web.com/',
940
+ imageUrl: 'https://path-to-image.com/',
941
+ additionalImages: [{
942
+ url: 'https://path-to-tiny-image.com/'
943
+ }]
944
+ }, {
945
+ products: [{
946
+ title: 'Starseed Premium Script',
947
+ brand: 'Starseed',
948
+ price: 'Rp 150.000',
949
+ salePrice: 'Rp 75.000',
950
+ productUrl: 'https://path-to-web.com/',
951
+ imageUrl: 'https://path-to-image.com/'
952
+ }, {
953
+ title: 'Self-Bot Script',
954
+ brand: 'Starseed',
955
+ price: 'Rp 50.000',
956
+ productUrl: 'https://path-to-web.com/',
957
+ imageUrl: 'https://path-to-image.com/',
958
+ additionalImages: [{
959
+ url: 'https://path-to-tiny-image.com/'
960
+ }]
961
+ }]
962
+ }, {
963
+ latex: 'https://quicklatex.com/cache3/82/ql_0676ade0cd04eda37aeb3d0bcd427682_l3.png',
964
+ expression: 'x^2 + 2x + 1',
965
+ mime: 'image/png',
966
+ width: 603,
967
+ height: 111,
968
+ fontHeight: 83.5,
969
+ padding: 15
970
+ }, {
971
+ text: '- Citation:',
972
+ entities: [{
973
+ title: 'Example of Citation',
974
+ citationUrl: 'https://wa.me/0',
975
+ displayName: '@DarkYasiyaNew/starforge'
976
+ }]
977
+ }, {
978
+ text: '- Inline Link:',
979
+ entities: [{
980
+ inlineUrl: 'https://wa.me/0',
981
+ displayName: '@DarkYasiyaNew/starforge',
982
+ isTrusted: true
983
+ }]
984
+ }, {
985
+ text: '- LaTeX:',
986
+ entities: [{
987
+ expression: 'x^2 + 2x + 1',
988
+ latex: 'https://quicklatex.com/cache3/82/ql_0676ade0cd04eda37aeb3d0bcd427682_l3.png',
989
+ width: 603,
990
+ height: 111,
991
+ fontHeight: 83.5,
992
+ padding: 15
993
+ }]
994
+ }, {
995
+ suggestion: '@DarkYasiyaNew/starforge'
996
+ }, {
997
+ suggestions: ['@DarkYasiyaNew/starforge', ' Helper', '']
998
+ }, {
999
+ suggestions: ['@DarkYasiyaNew/starforge', 'Rich Response', 'Scroll Layout'],
1000
+ canScroll: true
1001
+ }, {
1002
+ tip: '@DarkYasiyaNew/starforge'
1003
+ }, {
1004
+ foaText: '# đŸ”Ĩ LARGE Text'
1005
+ }, {
1006
+ compactEntity: [{
1007
+ title: 'my name',
1008
+ subtitle: 'my subtitle',
1009
+ secondarySubtitle: 'my secondary subtitle',
1010
+ url: 'https://github.com/DarkYasiyaNew/starforge',
1011
+ entityType: 'FOLLOW',
1012
+ actionType: 'PAGE',
1013
+ isVerified: true,
1014
+ imageUrl: 'https://path-to-tiny-image.com/'
1015
+ }]
1016
+ }, {
1017
+ queryStatus: 'FETCHED',
1018
+ motivation: 'Every journey begins with a place worth remembering.',
1019
+ mapItems: [{
1020
+ id: String(Date.now()),
1021
+ name: 'Starforge Observatory',
1022
+ description: 'A quiet little place beneath the city lights, perfect for curious minds, late-night conversations, and watching the stars.',
1023
+ location: {
1024
+ latitude: -6.175392,
1025
+ longitude: 106.824964
1026
+ },
1027
+ address: {
1028
+ street: 'Jl. Langit Senja No. 42',
1029
+ region: 'Sri Lanka',
1030
+ country: 'LK'
1031
+ },
1032
+ priceLevel: '$$',
1033
+ openingStatus: 'OPEN',
1034
+ type: 'PLACE',
1035
+ timeZone: 'Asia/Colombo',
1036
+ rating: { avgRating: 4.8 },
1037
+ imageUrl: 'https://raw.githubusercontent.com/Dark-Yasiya/DARKYASIYA-DATABASE/main/MEDIA/IMAGE/yasiya-md-v3.jpg'
1038
+ }]
1039
+ }, {
1040
+ actionUrls: [{
1041
+ text: '💰 Donate Me!',
1042
+ url: 'https://yasiyamd.lk/DarkYasiyaNew'
1043
+ }, {
1044
+ text: '🌐 Google',
1045
+ url: 'https://www.google.com/'
1046
+ }]
1047
+ }, {
1048
+ searchResults: [{
1049
+ displayName: 'Simple Helper',
1050
+ sourceUrl: 'https://path-to-web.com/',
1051
+ faviconUrl: 'https://path-to-tiny-image.com/',
1052
+ mime: 'image/jpeg'
1053
+ }]
1054
+ }], m, {
1055
+ notify: false,
1056
+ disclaimerText: 'Example Usage of sendRich()',
1057
+ disableEdit: false,
1058
+ disableForward: false,
1059
+ forceAsFooter: false
1060
+ })
1061
+ ```
1062
+
1063
+ #### â†Šī¸ Copy & Forward
1064
+
1065
+ `sendCopy(jid: string, content: object, options?: object)`
1066
+
1067
+ ```javascript
1068
+ client.sendCopy(jid, m)
1069
+
1070
+ // Custom forwarding score
1071
+ client.sendCopy(jid, m, { forwardScore: 1000 })
1072
+
1073
+ // Disable forwarding score
1074
+ client.sendCopy(jid, m, { forwardScore: false })
1075
+
1076
+ // Quote a message
1077
+ client.sendCopy(jid, m, { quote: m })
1078
+ ```
1079
+
1080
+ #### 🧰 Additional Options
1081
+
1082
+ > 💡 Tip: You can use the following additional options in the `options` parameter of every function returned by `extendSocket()`.
1083
+
1084
+ ```javascript
1085
+ // Add an "AI" icon (only available in private chats)
1086
+ client.sendText(jid, '🤖 Hello', m, null, {
1087
+ isAi: true
1088
+ })
1089
+
1090
+ // The message will disappear 1 second after you open the chat
1091
+ client.sendText(jid, 'đŸ—„ī¸ Secret Password: *4640*', m, null, {
1092
+ readTimeout: 1
1093
+ })
1094
+
1095
+ // Send the message as a group status
1096
+ client.sendText(jid, 'Group Status ✨', null, null, {
1097
+ groupStatus: true,
1098
+
1099
+ // Optional, use this if you want to enable Close Friends
1100
+ closeFriends: {
1101
+ name: 'To My Friends!',
1102
+ emoji: '🍅'
1103
+ }
1104
+ })
1105
+
1106
+ // Force send with a spoiler, hiding the content between || pipes
1107
+ client.sendText(jid, '👋đŸģ Hello ||world!||', null, null, {
1108
+ spoiler: true
1109
+ })
1110
+ ```
1111
+
1112
+ ### 👤 Chats
1113
+
1114
+ #### `rejectCall(callId: string, callCreatorJid: string)`
1115
+
1116
+ #### `resolveUserJid(jid: string)`
1117
+
1118
+ #### `updateMemberLabel(jid: string, label: string)`
1119
+
1120
+ #### `setChatEphemeral(jid: string, durationSecs: number)`
1121
+
1122
+ ### đŸ§ŗ Environments
1123
+
1124
+ The following environment variables are supported. They can be configured through the environment or a `.env` file using [`dotenv`](https://www.npmjs.com/package/dotenv).
1125
+
1126
+ ```ini
1127
+ # .env
1128
+
1129
+ # Defaults to os.tmpdir() when unset
1130
+ TEMPORARY_PATH=
1131
+
1132
+ FFMPEG_PATH=ffmpeg
1133
+
1134
+ FFPROBE_PATH=ffprobe
1135
+
1136
+ FFMPEG_TIMEOUT=60000
1137
+
1138
+ FFPROBE_TIMEOUT=60000
1139
+
1140
+ FETCH_TIMEOUT=60000
1141
+ ```
1142
+
1143
+ ### â¤ī¸ Credits
1144
+
1145
+ <!-- Please do not replace my name with yours. It's disrespectful. -->
1146
+
1147
+ **This project is created and maintained by [Dark Yasiya](https://github.com/DarkYasiyaNew)**
1148
+
1149
+ Thanks to the [](https://github.com/DarkYasiyanew/YASIYA-MD/) maintainers and contributors for providing an amazing and modern TypeScript library for interacting with the WhatsApp Web API.
1150
+
1151
+ Please do not remove or alter the original credits, copyright notices, or attributions.
1152
+
1153
+ ### 📄 License
1154
+
1155
+ This library is licensed under the [Apache License 2.0](LICENSE)