jagproject 2.2.9 → 2.2.12

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 (2) hide show
  1. package/README.MD +1591 -131
  2. package/package.json +1 -1
package/README.MD CHANGED
@@ -1,207 +1,635 @@
1
- ### wileys
2
1
 
3
- WhatsApp Web API Library
2
+ # <div align='center'>Baileys Modification</div>
4
3
 
5
- wileys is a modern TypeScript-based library for WhatsApp Web API integration with built-in fixes for group identifiers like @lid and @jid.
4
+ <div align="center">
6
5
 
7
- Donation (Solana)
6
+ <img src="https://cdn.antaranews.com/cache/800x533/2023/05/17/Screenshot_20230517_132501_Gallery.jpg" />
8
7
 
9
- ```
10
- 8xN639anSq5q64793tseCjPaXNgXEPaKxr91CKEuggKd
11
- ```
8
+ <a href="https://www.npmjs.com/package/jagoan-project">
9
+ <img src="https://img.shields.io/npm/v/jagoan-project?color=red&label=Version&logo=npm" alt="npm version" />
10
+ </a>
12
11
 
13
- ## Features
14
- @lid and @jid mapping
12
+ <a href="https://www.npmjs.com/package/jagoan-project">
13
+ <img src="https://img.shields.io/npm/dt/jagoan-project?color=red&label=Downloads&logo=npm" alt="npm downloads" />
14
+ </a>
15
15
 
16
- Multi-device support
16
+ <a href="https://whatsapp.com/channel/0029VanhMDo42DcjiRGJOc2m ">
17
+ <img src="https://img.shields.io/badge/WhatsApp-Channel-25D366?logo=whatsapp&logoColor=white" alt="WhatsApp Channel" />
18
+ </a>
17
19
 
18
- End-to-End Encryption support
20
+ </div>
19
21
 
20
- Handles all WhatsApp message types
22
+ ## 📖 Tentang Jagoan Project
21
23
 
22
- Fast and stable
23
- -----
24
+ **Jagoan Project** adalah modifikasi dokumentasi dari *baileys*, sebuah library modern berbasis TypeScript untuk integrasi WhatsApp Web API.
25
+ Library ini sudah mendukung sistem *multi-device*, enkripsi end-to-end, dan kompatibilitas tinggi untuk semua tipe pesan di WhatsApp.
26
+ Selain itu, Jagoan Project menghadirkan dokumentasi bergaya modern agar mudah dibaca dan dipahami oleh para pengembang.
24
27
 
25
- Installation
28
+ 📦 **Donasi (Qris)**
29
+ [Klik di sini untuk melihat QRIS](https://raw.githubusercontent.com/ChandraGO/Data-Jagoan-Project/refs/heads/master/qris.jpg)
26
30
 
27
- ```bash
28
- npm install wileys
29
- # or
30
- yarn add wileys
31
- ```
32
31
 
33
- Quick Start
32
+ ---
34
33
 
35
- ```typescript
36
- import makeWASocket from 'wileys'
37
- import { getSenderLid, toJid } from 'wileys'
34
+ ## ⚙️ Fitur Utama
38
35
 
39
- const sock = makeWASocket({ printQRInTerminal: true })
36
+ - Pemetaaan `@lid` dan `@jid`
37
+ - Dukungan *multi-device*
38
+ - Dukungan enkripsi *End-to-End*
39
+ - Menangani semua jenis pesan WhatsApp
40
+ - Kinerja cepat dan stabil ⚡
40
41
 
41
- sock.ev.on('messages.upsert', ({ messages }) => {
42
- const msg = messages[0]
43
- const info = getSenderLid(msg)
44
- const jid = toJid(info.lid)
45
- console.log('normalized jid:', jid)
46
- })
42
+ ---
43
+
44
+ ## 📦 Instalasi
45
+
46
+ Gunakan salah satu perintah berikut untuk menginstal:
47
+
48
+ ```bash
49
+ npm install jagproject
50
+ # atau
51
+ yarn add jagproject
47
52
  ```
48
53
 
49
- Advanced Usage (Multi-file Auth)
54
+ ---
50
55
 
51
- ```typescript
52
- import makeWASocket, { useMultiFileAuthState } from "wileys"
53
56
 
54
- async function start() {
55
- const { state, saveCreds } = await useMultiFileAuthState("auth_info")
56
- const sock = makeWASocket({ auth: state, printQRInTerminal: true })
57
+ # Documentation
57
58
 
58
- sock.ev.on("creds.update", saveCreds)
59
- sock.ev.on("messages.upsert", ({ messages }) => {
60
- for (const m of messages) {
61
- console.log(m.key.remoteJid, m.message?.conversation)
62
- }
63
- })
64
- }
59
+ - [Connecting Account](#connecting-account)
60
+ - [Connect with QR-CODE](#starting-socket-with-qr-code)
61
+ - [Connect with Pairing Code](#starting-socket-with-pairing-code)
62
+ - [Receive Full History](#receive-full-history)
63
+ - [Important Notes About Socket Config](#important-notes-about-socket-config)
64
+ - [Caching Group Metadata (Recommended)](#caching-group-metadata-recommended)
65
+ - [Improve Retry System & Decrypt Poll Votes](#improve-retry-system--decrypt-poll-votes)
66
+ - [Receive Notifications in Whatsapp App](#receive-notifications-in-whatsapp-app)
65
67
 
66
- start()
67
- ```
68
+ - [Save Auth Info](#saving--restoring-sessions)
69
+ - [Handling Events](#handling-events)
70
+ - [Example to Start](#example-to-start)
71
+ - [Decrypt Poll Votes](#decrypt-poll-votes)
72
+ - [Summary of Events on First Connection](#summary-of-events-on-first-connection)
73
+ - [Implementing a Data Store](#implementing-a-data-store)
74
+ - [Whatsapp IDs Explain](#whatsapp-ids-explain)
75
+ - [Utility Functions](#utility-functions)
76
+ - [Sending Messages](#sending-messages)
77
+ - [Non-Media Messages](#non-media-messages)
78
+ - [Buttons Message](#buttons-message)
79
+ - [Buttons Flow](#buttons-flow)
80
+ - [Interactive Message](#interactive-message)
81
+ - [Text Message](#text-message)
82
+ - [Quote Message](#quote-message-works-with-all-types)
83
+ - [Mention User](#mention-user-works-with-most-types)
84
+ - [Mention Status](#mention-status)
85
+ - [Result Poll From Newsletter](#result-poll-from-newsletter)
86
+ - [SendAlbumMessage](#send-album-message)
87
+ - [Interactive Response](#interactive-response)
88
+ - [Request Payment](#request-payment)
89
+ - [Event Message](#event-message)
90
+ - [Interactive](#interactive)
91
+ - [Forward Messages](#forward-messages)
92
+ - [Location Message](#location-message)
93
+ - [Contact Message](#contact-message)
94
+ - [Reaction Message](#reaction-message)
95
+ - [Pin Message](#pin-message)
96
+ - [Poll Message](#poll-message)
97
+ - [Sending with Link Preview](#sending-messages-with-link-previews)
98
+ - [Media Messages](#media-messages)
99
+ - [Gif Message](#gif-message)
100
+ - [Video Message](#video-message)
101
+ - [Audio Message](#audio-message)
102
+ - [Image Message](#image-message)
103
+ - [ViewOnce Message](#view-once-message)
104
+ - [Modify Messages](#modify-messages)
105
+ - [Delete Messages (for everyone)](#deleting-messages-for-everyone)
106
+ - [Edit Messages](#editing-messages)
107
+ - [Manipulating Media Messages](#manipulating-media-messages)
108
+ - [Thumbnail in Media Messages](#thumbnail-in-media-messages)
109
+ - [Downloading Media Messages](#downloading-media-messages)
110
+ - [Re-upload Media Message to Whatsapp](#re-upload-media-message-to-whatsapp)
111
+ - [Reject Call](#reject-call)
112
+ - [Send States in Chat](#send-states-in-chat)
113
+ - [Reading Messages](#reading-messages)
114
+ - [Update Presence](#update-presence)
115
+ - [Modifying Chats](#modifying-chats)
116
+ - [Archive a Chat](#archive-a-chat)
117
+ - [Mute/Unmute a Chat](#muteunmute-a-chat)
118
+ - [Mark a Chat Read/Unread](#mark-a-chat-readunread)
119
+ - [Delete a Message for Me](#delete-a-message-for-me)
120
+ - [Delete a Chat](#delete-a-chat)
121
+ - [Star/Unstar a Message](#starunstar-a-message)
122
+ - [Disappearing Messages](#disappearing-messages)
123
+ - [User Querys](#user-querys)
124
+ - [Check If ID Exists in Whatsapp](#check-if-id-exists-in-whatsapp)
125
+ - [Query Chat History (groups too)](#query-chat-history-groups-too)
126
+ - [Fetch Status](#fetch-status)
127
+ - [Fetch Profile Picture (groups too)](#fetch-profile-picture-groups-too)
128
+ - [Fetch Bussines Profile (such as description or category)](#fetch-bussines-profile-such-as-description-or-category)
129
+ - [Fetch Someone's Presence (if they're typing or online)](#fetch-someones-presence-if-theyre-typing-or-online)
130
+ - [Change Profile](#change-profile)
131
+ - [Change Profile Status](#change-profile-status)
132
+ - [Change Profile Name](#change-profile-name)
133
+ - [Change Display Picture (groups too)](#change-display-picture-groups-too)
134
+ - [Remove display picture (groups too)](#remove-display-picture-groups-too)
135
+ - [Groups](#groups)
136
+ - [Create a Group](#create-a-group)
137
+ - [Add/Remove or Demote/Promote](#addremove-or-demotepromote)
138
+ - [Change Subject (name)](#change-subject-name)
139
+ - [Change Description](#change-description)
140
+ - [Change Settings](#change-settings)
141
+ - [Leave a Group](#leave-a-group)
142
+ - [Get Invite Code](#get-invite-code)
143
+ - [Revoke Invite Code](#revoke-invite-code)
144
+ - [Join Using Invitation Code](#join-using-invitation-code)
145
+ - [Get Group Info by Invite Code](#get-group-info-by-invite-code)
146
+ - [Query Metadata (participants, name, description...)](#query-metadata-participants-name-description)
147
+ - [Join using groupInviteMessage](#join-using-groupinvitemessage)
148
+ - [Get Request Join List](#get-request-join-list)
149
+ - [Approve/Reject Request Join](#approvereject-request-join)
150
+ - [Get All Participating Groups Metadata](#get-all-participating-groups-metadata)
151
+ - [Toggle Ephemeral](#toggle-ephemeral)
152
+ - [Change Add Mode](#change-add-mode)
153
+ - [Privacy](#privacy)
154
+ - [Block/Unblock User](#blockunblock-user)
155
+ - [Get Privacy Settings](#get-privacy-settings)
156
+ - [Get BlockList](#get-blocklist)
157
+ - [Update LastSeen Privacy](#update-lastseen-privacy)
158
+ - [Update Online Privacy](#update-online-privacy)
159
+ - [Update Profile Picture Privacy](#update-profile-picture-privacy)
160
+ - [Update Status Privacy](#update-status-privacy)
161
+ - [Update Read Receipts Privacy](#update-read-receipts-privacy)
162
+ - [Update Groups Add Privacy](#update-groups-add-privacy)
163
+ - [Update Default Disappearing Mode](#update-default-disappearing-mode)
164
+ - [Broadcast Lists & Stories](#broadcast-lists--stories)
165
+ - [Send Broadcast & Stories](#send-broadcast--stories)
166
+ - [Query a Broadcast List's Recipients & Name](#query-a-broadcast-lists-recipients--name)
167
+ - [Writing Custom Functionality](#writing-custom-functionality)
168
+ - [Enabling Debug Level in Baileys Logs](#enabling-debug-level-in-baileys-logs)
169
+ - [How Whatsapp Communicate With Us](#how-whatsapp-communicate-with-us)
170
+ - [Register a Callback for Websocket Events](#register-a-callback-for-websocket-events)
171
+
172
+ ## 🔗 Menghubungkan Akun
173
+
174
+ WhatsApp provides a multi-device API that allows Baileys to be authenticated as a second WhatsApp client by scanning a **QR code** or **Pairing Code** with WhatsApp on your phone.
175
+
176
+ ### 🔹 Memulai Socket dengan **Kode QR**
68
177
 
69
- WhatsApp Connection
178
+ > [!TIP]
179
+ > You can customize browser name if you connect with **QR-CODE**, with `Browser` constant, we have some browsers config, **see [here](https://baileys.whiskeysockets.io/types/BrowsersMap.html)**
70
180
 
71
- Connect with QR Code
181
+ ```javascript
182
+ const { default: makeWASocket } = require("jagproject")
72
183
 
73
- ```typescript
74
- import makeWASocket, { Browsers } from 'wileys'
75
184
 
76
185
  const sock = makeWASocket({
186
+ // can provide additional config here
77
187
  browser: Browsers.ubuntu('My App'),
78
188
  printQRInTerminal: true
79
189
  })
80
190
  ```
81
191
 
82
- Connect with Pairing Code
192
+ If the connection is successful, you will see a QR code printed on your terminal screen, scan it with WhatsApp on your phone and you'll be logged in!
193
+
194
+ ### 🔹 Memulai Socket dengan **Kode Pairing**
195
+
196
+
197
+ > [!IMPORTANT]
198
+ > Pairing Code isn't Mobile API, it's a method to connect Whatsapp Web without QR-CODE, you can connect only with one device, see [here](https://faq.whatsapp.com/1324084875126592/?cms_platform=web)
83
199
 
84
- ```typescript
85
- import makeWASocket from 'wileys'
200
+ The phone number can't have `+` or `()` or `-`, only numbers, you must provide country code
201
+
202
+ ```javascript
203
+ const { default: makeWASocket } = require("jagproject")
86
204
 
87
205
  const sock = makeWASocket({
88
- printQRInTerminal: false
206
+ // can provide additional config here
207
+ printQRInTerminal: false //need to be false
89
208
  })
90
209
 
210
+ - Normal Pairing
91
211
  if (!sock.authState.creds.registered) {
92
- const number = '6281234567890'
212
+ const number = 'XXXXXXXXXXX'
93
213
  const code = await sock.requestPairingCode(number)
94
- console.log('Pairing code:', code)
214
+ console.log(code)
215
+ }
216
+
217
+ - Costum Pairing
218
+ if (!sock.authState.creds.registered) {
219
+ const pair = "12345678" // only 8 digit numbers or letters (no more or less)
220
+ const number = 'XXXXXXXXXXX'
221
+ const code = await sock.requestPairingCode(number, pair)
222
+ console.log(code)
95
223
  }
96
224
  ```
97
225
 
98
- How to Get Participant JID from GroupMetadata
226
+ ### 🔹 Menerima Riwayat Penuh
99
227
 
100
- ```typescript
101
- import makeWASocket from 'wileys'
228
+ 1. Set `syncFullHistory` as `true`
229
+ 2. Baileys, by default, use chrome browser config
230
+ - If you'd like to emulate a desktop connection (and receive more message history), this browser setting to your Socket config:
102
231
 
103
- const sock = makeWASocket({
104
- // socket configuration
232
+ ```javascript
233
+ const sock = makeWASocket({
234
+ ...otherOpts,
235
+ // can use Windows, Ubuntu here too
236
+ browser: Browsers.macOS('Desktop'),
237
+ syncFullHistory: true
105
238
  })
239
+ ```
106
240
 
107
- // Get group metadata
108
- const groupJid = '123456789-123345@g.us'
109
- const metadata = await sock.groupMetadata(groupJid)
241
+ ## ⚙️ Catatan Penting tentang Konfigurasi Socket
110
242
 
111
- // Get all participant JIDs
112
- const participantJids = metadata.participants.map(participant => participant.id)
113
- console.log('Participant JIDs:', participantJids)
243
+ ### 🧠 Caching Metadata Grup (Direkomendasikan)
244
+ - If you use baileys for groups, we recommend you to set `cachedGroupMetadata` in socket config, you need to implement a cache like this:
114
245
 
115
- // Resolve LID to JID for each participant
116
- for (const participant of metadata.participants) {
117
- const lid = participant.id
118
- const jid = toJid(lid)
119
- console.log(`LID: ${lid} -> JID: ${jid}`)
120
- }
246
+ ```javascript
247
+ const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false})
121
248
 
122
- // Utility function example
123
- async function getAllGroupParticipantsJid(groupJid: string) {
124
- const metadata = await sock.groupMetadata(groupJid)
125
- return metadata.participants.map(p => ({
126
- lid: p.id,
127
- jid: toJid(p.id),
128
- isAdmin: p.admin !== undefined
129
- }))
130
- }
249
+ const sock = makeWASocket({
250
+ cachedGroupMetadata: async (jid) => groupCache.get(jid)
251
+ })
131
252
 
132
- // Usage
133
- const participants = await getAllGroupParticipantsJid(groupJid)
134
- participants.forEach(p => {
135
- console.log(`Participant: ${p.jid}, Admin: ${p.isAdmin}`)
136
- })
253
+ sock.ev.on('groups.update', async ([event]) => {
254
+ const metadata = await sock.groupMetadata(event.id)
255
+ groupCache.set(event.id, metadata)
256
+ })
257
+
258
+ sock.ev.on('group-participants.update', async (event) => {
259
+ const metadata = await sock.groupMetadata(event.id)
260
+ groupCache.set(event.id, metadata)
261
+ })
262
+ ```
263
+
264
+ ### 🔁 Perbaiki Sistem Retry & Dekripsi Polling
265
+ - If you want to improve sending message, retrying when error occurs and decrypt poll votes, you need to have a store and set `getMessage` config in socket like this:
266
+ ```javascript
267
+ const sock = makeWASocket({
268
+ getMessage: async (key) => await getMessageFromStore(key)
269
+ })
270
+ ```
271
+
272
+ ### 🔔 Menerima Notifikasi di Aplikasi WhatsApp
273
+ - If you want to receive notifications in whatsapp app, set `markOnlineOnConnect` to `false`
274
+ ```javascript
275
+ const sock = makeWASocket({
276
+ markOnlineOnConnect: false
277
+ })
278
+ ```
279
+ ## 📦 Menyimpan & Mengembalikan Sesi
280
+
281
+ You obviously don't want to keep scanning the QR code every time you want to connect.
282
+
283
+ So, you can load the credentials to log back in:
284
+ ```javascript
285
+ const makeWASocket = require("jagproject").default;
286
+ const { useMultiFileAuthState } = require("jagproject");
287
+
288
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
289
+
290
+ // will use the given state to connect
291
+ // so if valid credentials are available -- it'll connect without QR
292
+ const sock = makeWASocket({ auth: state })
293
+
294
+ // this will be called as soon as the credentials are updated
295
+ sock.ev.on('creds.update', saveCreds)
137
296
  ```
138
297
 
139
- Using Cache for Group Metadata (Recommended)
298
+ > [!IMPORTANT]
299
+ > `useMultiFileAuthState` is a utility function to help save the auth state in a single folder, this function serves as a good guide to help write auth & key states for SQL/no-SQL databases, which I would recommend in any production grade system.
140
300
 
141
- ```typescript
142
- import { NodeCache } from 'node-cache'
301
+ > [!NOTE]
302
+ > When a message is received/sent, due to signal sessions needing updating, the auth keys (`authState.keys`) will update. Whenever that happens, you must save the updated keys (`authState.keys.set()` is called). Not doing so will prevent your messages from reaching the recipient & cause other unexpected consequences. The `useMultiFileAuthState` function automatically takes care of that, but for any other serious implementation -- you will need to be very careful with the key state management.
143
303
 
144
- const groupCache = new NodeCache({ stdTTL: 5 * 60 })
304
+ ## 📡 Penanganan Event
145
305
 
146
- const sock = makeWASocket({
147
- cachedGroupMetadata: async (jid) => groupCache.get(jid)
148
- })
306
+ - Baileys uses the EventEmitter syntax for events.
307
+ They're all nicely typed up, so you shouldn't have any issues with an Intellisense editor like VS Code.
149
308
 
150
- // Update cache on group changes
151
- sock.ev.on('groups.update', async ([event]) => {
152
- const metadata = await sock.groupMetadata(event.id)
153
- groupCache.set(event.id, metadata)
154
- })
309
+ > [!IMPORTANT]
310
+ > **The events are [these](https://baileys.whiskeysockets.io/types/BaileysEventMap.html)**, it's important you see all events
155
311
 
156
- sock.ev.on('group-participants.update', async (event) => {
157
- const metadata = await sock.groupMetadata(event.id)
158
- groupCache.set(event.id, metadata)
312
+ You can listen to these events like this:
313
+ ```javascript
314
+ const sock = makeWASocket()
315
+ sock.ev.on('messages.upsert', ({ messages }) => {
316
+ console.log('got messages', messages)
159
317
  })
160
318
  ```
161
319
 
162
- Connection Handling with Auto-Reconnect
320
+ ### 🛠️ Contoh Awal
321
+
322
+ > [!NOTE]
323
+ > This example includes basic auth storage too
163
324
 
164
- ```typescript
165
- import makeWASocket, { DisconnectReason, useMultiFileAuthState } from 'wileys'
166
- import { Boom } from '@hapi/boom'
325
+ ```javascript
326
+ const makeWASocket = require("jagproject").default;
327
+ const { DisconnectReason, useMultiFileAuthState } = require("jagproject");
328
+ const Boom = require('@hapi/boom');
167
329
 
168
- async function connectToWhatsApp() {
169
- const { state, saveCreds } = await useMultiFileAuthState('auth_info')
330
+ async function connectToWhatsApp () {
331
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
170
332
  const sock = makeWASocket({
333
+ // can provide additional config here
171
334
  auth: state,
172
335
  printQRInTerminal: true
173
336
  })
174
-
175
337
  sock.ev.on('connection.update', (update) => {
176
338
  const { connection, lastDisconnect } = update
177
- if (connection === 'close') {
339
+ if(connection === 'close') {
178
340
  const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
179
- console.log('Connection closed, reconnecting:', shouldReconnect)
180
- if (shouldReconnect) {
341
+ console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
342
+ // reconnect if not logged out
343
+ if(shouldReconnect) {
181
344
  connectToWhatsApp()
182
345
  }
183
- } else if (connection === 'open') {
184
- console.log('Connection opened')
346
+ } else if(connection === 'open') {
347
+ console.log('opened connection')
185
348
  }
186
349
  })
187
-
350
+ sock.ev.on('messages.upsert', event => {
351
+ for (const m of event.messages) {
352
+ console.log(JSON.stringify(m, undefined, 2))
353
+
354
+ console.log('replying to', m.key.remoteJid)
355
+ await sock.sendMessage(m.key.remoteJid!, { text: 'Hello Word' })
356
+ }
357
+ })
358
+
359
+ // to storage creds (session info) when it updates
188
360
  sock.ev.on('creds.update', saveCreds)
189
361
  }
190
-
362
+ // run in main file
191
363
  connectToWhatsApp()
192
364
  ```
193
365
 
194
- Sending Messages
366
+ > [!IMPORTANT]
367
+ > In `messages.upsert` it's recommended to use a loop like `for (const message of event.messages)` to handle all messages in array
368
+
369
+ ### 🔐 Dekripsi Pilihan Polling
370
+
371
+ - By default poll votes are encrypted and handled in `messages.update`
372
+ - That's a simple example
373
+ ```javascript
374
+ sock.ev.on('messages.update', event => {
375
+ for(const { key, update } of event) {
376
+ if(update.pollUpdates) {
377
+ const pollCreation = await getMessage(key)
378
+ if(pollCreation) {
379
+ console.log(
380
+ 'got poll update, aggregation: ',
381
+ getAggregateVotesInPollMessage({
382
+ message: pollCreation,
383
+ pollUpdates: update.pollUpdates,
384
+ })
385
+ )
386
+ }
387
+ }
388
+ }
389
+ })
390
+ ```
391
+
392
+ - `getMessage` is a [store](#implementing-a-data-store) implementation (in your end)
393
+
394
+ ### 🔎 Ringkasan Event pada Koneksi Pertama
395
+
396
+ 1. When you connect first time, `connection.update` will be fired requesting you to restart sock
397
+ 2. Then, history messages will be received in `messaging.history-set`
398
+
399
+ ## 💾 Mengimplementasikan Data Store
400
+
401
+ - Baileys does not come with a defacto storage for chats, contacts, or messages. However, a simple in-memory implementation has been provided. The store listens for chat updates, new messages, message updates, etc., to always have an up-to-date version of the data.
402
+
403
+ > [!IMPORTANT]
404
+ > I highly recommend building your own data store, as storing someone's entire chat history in memory is a terrible waste of RAM.
405
+
406
+ It can be used as follows:
407
+
408
+ ```javascript
409
+ const makeWASocket = require("jagproject").default;
410
+ const { makeInMemoryStore } = require("jagproject");
411
+ // the store maintains the data of the WA connection in memory
412
+ // can be written out to a file & read from it
413
+ const store = makeInMemoryStore({ })
414
+ // can be read from a file
415
+ store.readFromFile('./baileys_store.json')
416
+ // saves the state to a file every 10s
417
+ setInterval(() => {
418
+ store.writeToFile('./baileys_store.json')
419
+ }, 10_000)
420
+
421
+ const sock = makeWASocket({ })
422
+ // will listen from this socket
423
+ // the store can listen from a new socket once the current socket outlives its lifetime
424
+ store.bind(sock.ev)
425
+
426
+ sock.ev.on('chats.upsert', () => {
427
+ // can use 'store.chats' however you want, even after the socket dies out
428
+ // 'chats' => a KeyedDB instance
429
+ console.log('got chats', store.chats.all())
430
+ })
431
+
432
+ sock.ev.on('contacts.upsert', () => {
433
+ console.log('got contacts', Object.values(store.contacts))
434
+ })
435
+
436
+ ```
437
+
438
+ The store also provides some simple functions such as `loadMessages` that utilize the store to speed up data retrieval.
439
+
440
+ ## 🆔 Penjelasan ID WhatsApp
441
+
442
+ - `id` is the WhatsApp ID, called `jid` too, of the person or group you're sending the message to.
443
+ - It must be in the format ```[country code][phone number]@s.whatsapp.net```
444
+ - Example for people: ```+19999999999@s.whatsapp.net```.
445
+ - For groups, it must be in the format ``` 123456789-123345@g.us ```.
446
+ - For broadcast lists, it's `[timestamp of creation]@broadcast`.
447
+ - For stories, the ID is `status@broadcast`.
448
+
449
+ ## 🧰 Fungsi Utilitas
450
+
451
+ - `getContentType`, returns the content type for any message
452
+ - `getDevice`, returns the device from message
453
+ - `makeCacheableSignalKeyStore`, make auth store more fast
454
+ - `downloadContentFromMessage`, download content from any message
455
+
456
+ ## 💬 Mengirim Pesan
195
457
 
196
- Text Message
458
+ - Send all types of messages with a single function
459
+ - **[Here](https://baileys.whiskeysockets.io/types/AnyMessageContent.html) you can see all message contents supported, like text message**
460
+ - **[Here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html) you can see all options supported, like quote message**
197
461
 
198
- ```typescript
199
- await sock.sendMessage(jid, { text: 'Hello world' })
462
+ ```javascript
463
+ const jid: string
464
+ const content: AnyMessageContent
465
+ const options: MiscMessageGenerationOptions
466
+
467
+ sock.sendMessage(jid, content, options)
468
+ ```
469
+
470
+ ### ✉️ Pesan Non-Media
471
+
472
+ #### 🔘 Pesan Tombol (Buttons)
473
+ ```javascript
474
+ // send a buttons message!
475
+ sock.sendMessage(jid, {
476
+ text: "Hello World !",
477
+ footer: "jagproject - 2025",
478
+ buttons: [
479
+ {
480
+ buttonId: `🚀`,
481
+ buttonText: {
482
+ displayText: '🗿'
483
+ },
484
+ type: 1
485
+ }
486
+ ],
487
+ headerType: 1,
488
+ viewOnce: true
489
+ },{ quoted: null })
200
490
  ```
201
491
 
202
- Message with Mention
492
+ #### 🔁 Alur Tombol
493
+ ```javascript
494
+ sock.sendMessage(jid, {
495
+ text: "Hello Wolrd !;",
496
+ footer: "© jagproject Dev",
497
+ buttons: [
498
+ {
499
+ buttonId: '.tes',
500
+ buttonText: {
501
+ displayText: 'TESTING BOT'
502
+ },
503
+ type: 1,
504
+ },
505
+ {
506
+ buttonId: ' ',
507
+ buttonText: {
508
+ displayText: 'PRIVATE SCRIPT'
509
+ },
510
+ type: 1,
511
+ },
512
+ {
513
+ buttonId: 'action',
514
+ buttonText: {
515
+ displayText: 'ini pesan interactiveMeta'
516
+ },
517
+ type: 4,
518
+ nativeFlowInfo: {
519
+ name: 'single_select',
520
+ paramsJson: JSON.stringify({
521
+ title: 'message',
522
+ sections: [
523
+ {
524
+ title: 'jagproject - 2025',
525
+ highlight_label: '😜',
526
+ rows: [
527
+ {
528
+ header: 'HEADER',
529
+ title: 'TITLE',
530
+ description: 'DESCRIPTION',
531
+ id: 'YOUR ID',
532
+ },
533
+ {
534
+ header: 'HEADER',
535
+ title: 'TITLE',
536
+ description: 'DESCRIPTION',
537
+ id: 'YOUR ID',
538
+ },
539
+ ],
540
+ },
541
+ ],
542
+ }),
543
+ },
544
+ },
545
+ ],
546
+ headerType: 1,
547
+ viewOnce: true
548
+ }, { quoted: m });
549
+ ```
550
+
551
+ #### 🧩 Pesan Interaktif
552
+ ```javascript
553
+ let msg = generateWAMessageFromContent(m.chat, {
554
+ viewOnceMessage: {
555
+ message: {
556
+ "messageContextInfo": {
557
+ "deviceListMetadata": {},
558
+ "deviceListMetadataVersion": 2
559
+ },
560
+ interactiveMessage: proto.Message.InteractiveMessage.create({
561
+ body: proto.Message.InteractiveMessage.Body.create({
562
+ text: "jagproject Dev"
563
+ }),
564
+ footer: proto.Message.InteractiveMessage.Footer.create({
565
+ text: "Bot"
566
+ }),
567
+ header: proto.Message.InteractiveMessage.Header.create({
568
+ title: "Igna",
569
+ subtitle: "test",
570
+ hasMediaAttachment: false
571
+ }),
572
+ nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({
573
+ buttons: [
574
+ {
575
+ "name": "single_select",
576
+ "buttonParamsJson": "{\"title\":\"title\",\"sections\":[{\".menu\":\".play dj webito\",\"highlight_label\":\"label\",\"rows\":[{\"header\":\"header\",\"title\":\"title\",\"description\":\"description\",\"id\":\"id\"},{\"header\":\"header\",\"title\":\"title\",\"description\":\"description\",\"id\":\"id\"}]}]}"
577
+ },
578
+ {
579
+ "name": "cta_reply",
580
+ "buttonParamsJson": "{\"display_text\":\"quick_reply\",\"id\":\"message\"}"
581
+ },
582
+ {
583
+ "name": "cta_url",
584
+ "buttonParamsJson": "{\"display_text\":\"url\",\"url\":\"https://www.google.com\",\"merchant_url\":\"https://www.google.com\"}"
585
+ },
586
+ {
587
+ "name": "cta_call",
588
+ "buttonParamsJson": "{\"display_text\":\"call\",\"id\":\"message\"}"
589
+ },
590
+ {
591
+ "name": "cta_copy",
592
+ "buttonParamsJson": "{\"display_text\":\"copy\",\"id\":\"123456789\",\"copy_code\":\"message\"}"
593
+ },
594
+ {
595
+ "name": "cta_reminder",
596
+ "buttonParamsJson": "{\"display_text\":\"Recordatorio\",\"id\":\"message\"}"
597
+ },
598
+ {
599
+ "name": "cta_cancel_reminder",
600
+ "buttonParamsJson": "{\"display_text\":\"cta_cancel_reminder\",\"id\":\"message\"}"
601
+ },
602
+ {
603
+ "name": "address_message",
604
+ "buttonParamsJson": "{\"display_text\":\"address_message\",\"id\":\"message\"}"
605
+ },
606
+ {
607
+ "name": "send_location",
608
+ "buttonParamsJson": ""
609
+ }
610
+ ],
611
+ })
612
+ })
613
+ }
614
+ }
615
+ }, {})
203
616
 
204
- ```typescript
617
+ return sock.relayMessage(msg.key.remoteJid, msg.message, { messageId: msg.key.id })
618
+ ```
619
+
620
+ #### 📝 Pesan Teks
621
+ ```javascript
622
+ await sock.sendMessage(jid, { text: 'hello word' })
623
+ ```
624
+
625
+ #### ❝ Pesan Quote (bekerja untuk semua tipe)
626
+ ```javascript
627
+ await sock.sendMessage(jid, { text: 'hello word' }, { quoted: message })
628
+ ```
629
+
630
+ #### 🏷️ Mention Pengguna (bekerja di kebanyakan tipe)
631
+ - @number is to mention in text, it's optional
632
+ ```javascript
205
633
  await sock.sendMessage(
206
634
  jid,
207
635
  {
@@ -211,23 +639,1055 @@ await sock.sendMessage(
211
639
  )
212
640
  ```
213
641
 
214
- Media Message
642
+ #### 📣 Mention Status
643
+ - [ jid ] If the Jid Group and Jid Private Chat are included in the JID list, try to make the JID group first starting from the Jid Private Chat or Jid Private Chat in the middle between the group Jid
644
+ ```javascript
645
+ await sock.StatusMentions(
646
+ {
647
+ text: "Hello", // or image / video / audio ( url or buffer )
648
+ },
649
+ [
650
+ "123456789123456789@g.us",
651
+ "123456789@s.whatsapp.net",
652
+ // Enter jid chat here
653
+ ]
654
+ )
655
+ ```
656
+
657
+ #### 📊 Hasil Poll dari Newsletter
658
+ ```javascript
659
+ await client.sendMessage(
660
+ jid,
661
+ {
662
+ pollResult: {
663
+ name: "Text poll",
664
+ votes: [["Options 1", 10], ["Options 2", 10]], // 10 For Fake Polling Count Results
665
+ }
666
+ }, { quoted : message }
667
+ )
668
+ ```
669
+
670
+ #### 🖼️ Mengirim Pesan Album
671
+ - url or buffer ( image or video )
672
+ ```javascript
673
+ await sock.sendAlbumMessage(
674
+ jid,
675
+ [
676
+ {
677
+ image: { url: "https://example.jpg" }, // or buffer
678
+ caption: "Hello World",
679
+ },
680
+ {
681
+ video: { url: "https://example.mp4" }, // or buffer
682
+ caption: "Hello World",
683
+ },
684
+ ],
685
+ {
686
+ quoted : message,
687
+ delay : 2000 // number in seconds
688
+ }
689
+ )
690
+
691
+ ```
692
+
693
+ #### 🔔 Respon Interaktif
694
+ ```javascript
695
+ await client.sendMessage(
696
+ jid,
697
+ {
698
+ buttonReply: {
699
+ text: 'Text',
700
+ nativeFlow: {
701
+ version: 3,
702
+ },
703
+ },
704
+ type: 'interactive',
705
+ ephemeral: true,
706
+ }
707
+ )
708
+
709
+ ```
710
+
711
+ #### 💳 Permintaan Pembayaran
712
+ ```javascript
713
+ - Example non media sticker
714
+ await client.sendMessage(
715
+ jid,
716
+ {
717
+ requestPayment: {
718
+ currency: "IDR",
719
+ amount: "10000000",
720
+ from: "123456@s.whatsapp.net",
721
+ note: "Hai Guys",
722
+ background: { ...background of the message }
723
+ }
724
+ },
725
+ { quoted : message }
726
+ )
727
+
728
+ - with media sticker buffer
729
+ await client.sendMessage(
730
+ jid,
731
+ {
732
+ requestPayment: {
733
+ currency: "IDR",
734
+ amount: "10000000",
735
+ from: "123456@s.whatsapp.net",
736
+ sticker: Buffer,
737
+ background: { ...background of the message }
738
+ }
739
+ },
740
+ { quoted : message }
741
+ )
742
+
743
+ - with media sticker url
744
+ await client.sendMessage(
745
+ jid,
746
+ {
747
+ requestPayment: {
748
+ currency: "IDR",
749
+ amount: "10000000",
750
+ from: "123456@s.whatsapp.net",
751
+ sticker: { url: Sticker Url },
752
+ background: { ...background of the message }
753
+ }
754
+ },
755
+ { quoted : message }
756
+ )
757
+ ```
758
+
759
+ #### 📆 Pesan Event
760
+ ```javascript
761
+ await client.sendMessage(
762
+ jid,
763
+ {
764
+ event: {
765
+ isCanceled: false, // or true for cancel event
766
+ name: "Name Event",
767
+ description: "Description Event",
768
+ location: {
769
+ degressLatitude: -0,
770
+ degressLongitude: - 0
771
+ },
772
+ link: Call Link,
773
+ startTime: m.messageTimestamp.low,
774
+ endTime: m.messageTimestamp.low + 86400, // 86400 is day in seconds
775
+ extraGuestsAllowed: true // or false
776
+ }
777
+ },
778
+ { quoted : message }
779
+ )
780
+ ```
781
+
782
+ #### 🔗 Interaktif
783
+ ```javascript
784
+ - Example non header media
785
+ await client.sendMessage(
786
+ jid,
787
+ {
788
+ text: "Description Of Messages", //Additional information
789
+ title: "Title Of Messages",
790
+ subtitle: "Subtitle Message",
791
+ footer: "Footer Messages",
792
+ interactiveButtons: [
793
+ {
794
+ name: "quick_reply",
795
+ buttonParamsJson: JSON.stringify({
796
+ display_text: "Display Button",
797
+ id: "ID"
798
+ })
799
+ },
800
+ {
801
+ name: "cta_url",
802
+ buttonParamsJson: JSON.stringify({
803
+ display_text: "Display Button",
804
+ url: "https://www.example.com"
805
+ })
806
+ }
807
+ ]
808
+ },
809
+ {
810
+ quoted : message
811
+ }
812
+ )
813
+
814
+ - Example with media
815
+ await client.sendMessage(
816
+ jid,
817
+ {
818
+ image: { url : "https://example.jpg" }, // Can buffer
819
+ caption: "Description Of Messages", //Additional information
820
+ title: "Title Of Messages",
821
+ subtitle: "Subtile Message",
822
+ footer: "Footer Messages",
823
+ media: true,
824
+ interactiveButtons: [
825
+ {
826
+ name: "quick_reply",
827
+ buttonParamsJson: JSON.stringify({
828
+ display_text: "Display Button",
829
+ id: "ID"
830
+ })
831
+ },
832
+ {
833
+ name: "cta_url",
834
+ buttonParamsJson: JSON.stringify({
835
+ display_text: "Display Button",
836
+ url: "https://www.example.com"
837
+ })
838
+ }
839
+ ]
840
+ },
841
+ {
842
+ quoted : message
843
+ }
844
+ )
845
+
846
+ - Example with header product
847
+ await client.sendMessage(
848
+ jid,
849
+ {
850
+ product: {
851
+ productImage: { url: "https://example.jpg }, //or buffer
852
+ productImageCount: 1,
853
+ title: "Title Product",
854
+ description: "Description Product",
855
+ priceAmount1000: 20000 * 1000,
856
+ currencyCode: "IDR",
857
+ retailerId: "Retail",
858
+ url: "https://example.com",
859
+ },
860
+ businessOwnerJid: "1234@s.whatsapp.net",
861
+ caption: "Description Of Messages", //Additional information
862
+ title: "Title Of Messages",
863
+ footer: "Footer Messages",
864
+ media: true,
865
+ interactiveButtons: [
866
+ {
867
+ name: "quick_reply",
868
+ buttonParamsJson: JSON.stringify({
869
+ display_text: "Display Button",
870
+ id: "ID"
871
+ })
872
+ },
873
+ {
874
+ name: "cta_url",
875
+ buttonParamsJson: JSON.stringify({
876
+ display_text: "Display Button",
877
+ url: "https://www.example.com"
878
+ })
879
+ }
880
+ ]
881
+ },
882
+ {
883
+ quoted : message
884
+ }
885
+ )
886
+ ```
887
+
888
+ #### 📤 Meneruskan Pesan
889
+ - You need to have message object, can be retrieved from [store](#implementing-a-data-store) or use a [message](https://baileys.whiskeysockets.io/types/WAMessage.html) object
890
+ ```javascript
891
+ const msg = getMessageFromStore() // implement this on your end
892
+ await sock.sendMessage(jid, { forward: msg }) // WA forward the message!
893
+ ```
894
+
895
+ #### 📍 Pesan Lokasi
896
+ ```javascript
897
+ await sock.sendMessage(
898
+ jid,
899
+ {
900
+ location: {
901
+ degreesLatitude: 24.121231,
902
+ degreesLongitude: 55.1121221
903
+ }
904
+ }
905
+ )
906
+ ```
907
+ #### 👤 Pesan Kontak
908
+ ```javascript
909
+ const vcard = 'BEGIN:VCARD\n' // metadata of the contact card
910
+ + 'VERSION:3.0\n'
911
+ + 'FN:Jeff Singh\n' // full name
912
+ + 'ORG:Ashoka Uni;\n' // the organization of the contact
913
+ + 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n' // WhatsApp ID + phone number
914
+ + 'END:VCARD'
915
+
916
+ await sock.sendMessage(
917
+ id,
918
+ {
919
+ contacts: {
920
+ displayName: 'Jeff',
921
+ contacts: [{ vcard }]
922
+ }
923
+ }
924
+ )
925
+ ```
926
+
927
+ #### ❤️ Pesan Reaksi
928
+ - You need to pass the key of message, you can retrieve from [store](#implementing-a-data-store) or use a [key](https://baileys.whiskeysockets.io/types/WAMessageKey.html) object
929
+ ```javascript
930
+ await sock.sendMessage(
931
+ jid,
932
+ {
933
+ react: {
934
+ text: '💖', // use an empty string to remove the reaction
935
+ key: message.key
936
+ }
937
+ }
938
+ )
939
+ ```
940
+
941
+ #### 📌 Pesan Pin
942
+ - You need to pass the key of message, you can retrieve from [store](#implementing-a-data-store) or use a [key](https://baileys.whiskeysockets.io/types/WAMessageKey.html) object
943
+
944
+ - Time can be:
945
+
946
+ | Time | Seconds |
947
+ |-------|----------------|
948
+ | 24h | 86.400 |
949
+ | 7d | 604.800 |
950
+ | 30d | 2.592.000 |
951
+
952
+ ```javascript
953
+ await sock.sendMessage(
954
+ jid,
955
+ {
956
+ pin: {
957
+ type: 1, // 0 to remove
958
+ time: 86400
959
+ key: message.key
960
+ }
961
+ }
962
+ )
963
+ ```
964
+
965
+ #### 🗳️ Pesan Poll
966
+ ```javascript
967
+ await sock.sendMessage(
968
+ jid,
969
+ {
970
+ poll: {
971
+ name: 'My Poll',
972
+ values: ['Option 1', 'Option 2', ...],
973
+ selectableCount: 1,
974
+ toAnnouncementGroup: false // or true
975
+ }
976
+ }
977
+ )
978
+ ```
979
+
980
+ ### 💬 Mengirim Pesan with Link Previews
981
+
982
+ 1. By default, wa does not have link generation when sent from the web
983
+ 2. Baileys has a function to generate the content for these link previews
984
+ 3. To enable this function's usage, add `link-preview-js` as a dependency to your project with `yarn add link-preview-js`
985
+ 4. Send a link:
986
+ ```javascript
987
+ await sock.sendMessage(
988
+ jid,
989
+ {
990
+ text: 'Hi, this was sent using https://github.com/whiskeysockets/baileys'
991
+ }
992
+ )
993
+ ```
994
+
995
+ ### 🎞️ Pesan Media
996
+
997
+ Sending media (video, stickers, images) is easier & more efficient than ever.
998
+
999
+ > [!NOTE]
1000
+ > In media messages, you can pass `{ stream: Stream }` or `{ url: Url }` or `Buffer` directly, you can see more [here](https://baileys.whiskeysockets.io/types/WAMediaUpload.html)
1001
+
1002
+ - When specifying a media url, Baileys never loads the entire buffer into memory; it even encrypts the media as a readable stream.
1003
+
1004
+ > [!TIP]
1005
+ > It's recommended to use Stream or Url to save memory
215
1006
 
216
- ```typescript
1007
+ #### 🎬 Pesan GIF
1008
+ - Whatsapp doesn't support `.gif` files, that's why we send gifs as common `.mp4` video with `gifPlayback` flag
1009
+ ```javascript
217
1010
  await sock.sendMessage(
218
1011
  jid,
219
1012
  {
220
- image: { url: 'path/to/image.jpg' },
221
- caption: 'Image description'
1013
+ video: fs.readFileSync('Media/ma_gif.mp4'),
1014
+ caption: 'hello word',
1015
+ gifPlayback: true
222
1016
  }
223
1017
  )
224
1018
  ```
225
1019
 
226
- Disclaimer
1020
+ #### 📹 Pesan Video
1021
+ ```javascript
1022
+ await sock.sendMessage(
1023
+ id,
1024
+ {
1025
+ video: {
1026
+ url: './Media/ma_gif.mp4'
1027
+ },
1028
+ caption: 'hello word',
1029
+ ptv: false // if set to true, will send as a `video note`
1030
+ }
1031
+ )
1032
+ ```
1033
+
1034
+ #### 🔊 Pesan Audio
1035
+ - To audio message work in all devices you need to convert with some tool like `ffmpeg` with this flags:
1036
+ ```bash
1037
+ codec: libopus //ogg file
1038
+ ac: 1 //one channel
1039
+ avoid_negative_ts
1040
+ make_zero
1041
+ ```
1042
+ - Example:
1043
+ ```bash
1044
+ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1045
+ ```
1046
+ ```javascript
1047
+ await sock.sendMessage(
1048
+ jid,
1049
+ {
1050
+ audio: {
1051
+ url: './Media/audio.mp3'
1052
+ },
1053
+ mimetype: 'audio/mp4'
1054
+ }
1055
+ )
1056
+ ```
1057
+
1058
+ #### 🖼️ Pesan Gambar
1059
+ ```javascript
1060
+ await sock.sendMessage(
1061
+ id,
1062
+ {
1063
+ image: {
1064
+ url: './Media/ma_img.png'
1065
+ },
1066
+ caption: 'hello word'
1067
+ }
1068
+ )
1069
+ ```
1070
+
1071
+ #### 👁️ View Once (Sekali Lihat)
1072
+
1073
+ - You can send all messages above as `viewOnce`, you only need to pass `viewOnce: true` in content object
1074
+
1075
+ ```javascript
1076
+ await sock.sendMessage(
1077
+ id,
1078
+ {
1079
+ image: {
1080
+ url: './Media/ma_img.png'
1081
+ },
1082
+ viewOnce: true, //works with video, audio too
1083
+ caption: 'hello word'
1084
+ }
1085
+ )
1086
+ ```
1087
+
1088
+ ## ✏️ Memodifikasi Pesan
1089
+
1090
+ ### 🗑️ Menghapus Pesan (untuk semua)
1091
+
1092
+ ```javascript
1093
+ const msg = await sock.sendMessage(jid, { text: 'hello word' })
1094
+ await sock.sendMessage(jid, { delete: msg.key })
1095
+ ```
1096
+
1097
+ **Note:** deleting for oneself is supported via `chatModify`, see in [this section](#modifying-chats)
1098
+
1099
+ ### 🖊️ Mengedit Pesan
1100
+
1101
+ - You can pass all editable contents here
1102
+ ```javascript
1103
+ await sock.sendMessage(jid, {
1104
+ text: 'updated text goes here',
1105
+ edit: response.key,
1106
+ });
1107
+ ```
1108
+
1109
+ ## 🛠️ Manipulasi Pesan Media
1110
+
1111
+ ### 🖼️ Thumbnail pada Pesan Media
1112
+ - For media messages, the thumbnail can be generated automatically for images & stickers provided you add `jimp` or `sharp` as a dependency in your project using `yarn add jimp` or `yarn add sharp`.
1113
+ - Thumbnails for videos can also be generated automatically, though, you need to have `ffmpeg` installed on your system.
1114
+
1115
+ ### ⬇️ Mengunduh Pesan Media
1116
+
1117
+ If you want to save the media you received
1118
+ ```javascript
1119
+ const { createWriteStream } = require('fs');
1120
+ const { downloadMediaMessage, getContentType } = require("jagproject");
1121
+
1122
+ sock.ev.on('messages.upsert', async ({ [m] }) => {
1123
+ if (!m.message) return // if there is no text or media message
1124
+ const messageType = getContentType(m) // get what type of message it is (text, image, video...)
1125
+
1126
+ // if the message is an image
1127
+ if (messageType === 'imageMessage') {
1128
+ // download the message
1129
+ const stream = await downloadMediaMessage(
1130
+ m,
1131
+ 'stream', // can be 'buffer' too
1132
+ { },
1133
+ {
1134
+ logger,
1135
+ // pass this so that baileys can request a reupload of media
1136
+ // that has been deleted
1137
+ reuploadRequest: sock.updateMediaMessage
1138
+ }
1139
+ )
1140
+ // save to file
1141
+ const writeStream = createWriteStream('./my-download.jpeg')
1142
+ stream.pipe(writeStream)
1143
+ }
1144
+ }
1145
+ ```
1146
+
1147
+ ### 🔁 Mengunggah Ulang Pesan Media ke WhatsApp
1148
+
1149
+ - WhatsApp automatically removes old media from their servers. For the device to access said media -- a re-upload is required by another device that has it. This can be accomplished using:
1150
+ ```javascript
1151
+ await sock.updateMediaMessage(msg)
1152
+ ```
1153
+
1154
+ ## 🚫 Menolak Panggilan
1155
+
1156
+ - You can obtain `callId` and `callFrom` from `call` event
1157
+
1158
+ ```javascript
1159
+ await sock.rejectCall(callId, callFrom)
1160
+ ```
1161
+
1162
+ ## 📡 Status Pengiriman di Chat
1163
+
1164
+ ### 📖 Membaca Pesan
1165
+ - A set of message [keys](https://baileys.whiskeysockets.io/types/WAMessageKey.html) must be explicitly marked read now.
1166
+ - You cannot mark an entire 'chat' read as it were with Baileys Web.
1167
+ This means you have to keep track of unread messages.
1168
+
1169
+ ```javascript
1170
+ const key: WAMessageKey
1171
+ // can pass multiple keys to read multiple messages as well
1172
+ await sock.readMessages([key])
1173
+ ```
1174
+
1175
+ The message ID is the unique identifier of the message that you are marking as read.
1176
+ On a `WAMessage`, the `messageID` can be accessed using ```messageID = message.key.id```.
1177
+
1178
+ ### 🟢 Memperbarui Presence
1179
+
1180
+ - ``` presence ``` can be one of [these](https://baileys.whiskeysockets.io/types/WAPresence.html)
1181
+ - The presence expires after about 10 seconds.
1182
+ - This lets the person/group with `jid` know whether you're online, offline, typing etc.
1183
+
1184
+ ```javascript
1185
+ await sock.sendPresenceUpdate('available', jid)
1186
+ ```
1187
+
1188
+ > [!NOTE]
1189
+ > If a desktop client is active, WA doesn't send push notifications to the device. If you would like to receive said notifications -- mark your Baileys client offline using `sock.sendPresenceUpdate('unavailable')`
1190
+
1191
+ ## 🗂️ Memodifikasi Chat
1192
+
1193
+ WA uses an encrypted form of communication to send chat/app updates. This has been implemented mostly and you can send the following updates:
1194
+
1195
+ > [!IMPORTANT]
1196
+ > If you mess up one of your updates, WA can log you out of all your devices and you'll have to log in again.
1197
+
1198
+ ### 🗃️ Arsipkan Chat
1199
+ ```javascript
1200
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
1201
+ await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)
1202
+ ```
1203
+ ### 🔕 Mute/Unmute Chat
1204
+
1205
+ - Supported times:
1206
+
1207
+ | Time | Miliseconds |
1208
+ |-------|-----------------|
1209
+ | Remove | null |
1210
+ | 8h | 86.400.000 |
1211
+ | 7d | 604.800.000 |
1212
+
1213
+ ```javascript
1214
+ // mute for 8 hours
1215
+ await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
1216
+ // unmute
1217
+ await sock.chatModify({ mute: null }, jid)
1218
+ ```
1219
+ ### ✅ Tandai Chat Baca/Belum Baca
1220
+ ```javascript
1221
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
1222
+ // mark it unread
1223
+ await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)
1224
+ ```
1225
+
1226
+ ### 🧹 Hapus Pesan untuk Saya
1227
+ ```javascript
1228
+ await sock.chatModify(
1229
+ {
1230
+ clear: {
1231
+ messages: [
1232
+ {
1233
+ id: 'ATWYHDNNWU81732J',
1234
+ fromMe: true,
1235
+ timestamp: '1654823909'
1236
+ }
1237
+ ]
1238
+ }
1239
+ },
1240
+ jid
1241
+ )
1242
+
1243
+ ```
1244
+ ### ❌ Hapus Chat
1245
+ ```javascript
1246
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
1247
+ await sock.chatModify({
1248
+ delete: true,
1249
+ lastMessages: [
1250
+ {
1251
+ key: lastMsgInChat.key,
1252
+ messageTimestamp: lastMsgInChat.messageTimestamp
1253
+ }
1254
+ ]
1255
+ },
1256
+ jid
1257
+ )
1258
+ ```
1259
+ ### 📌 Pin/Unpin Chat
1260
+ ```javascript
1261
+ await sock.chatModify({
1262
+ pin: true // or `false` to unpin
1263
+ },
1264
+ jid
1265
+ )
1266
+ ```
1267
+ ### ⭐ Star/Unstar Pesan
1268
+ ```javascript
1269
+ await sock.chatModify({
1270
+ star: {
1271
+ messages: [
1272
+ {
1273
+ id: 'messageID',
1274
+ fromMe: true // or `false`
1275
+ }
1276
+ ],
1277
+ star: true // - true: Star Message; false: Unstar Message
1278
+ }
1279
+ },
1280
+ jid
1281
+ )
1282
+ ```
1283
+
1284
+ ### 🕒 Pesan yang Menghilang (Disappearing)
1285
+
1286
+ - Ephemeral can be:
1287
+
1288
+ | Time | Seconds |
1289
+ |-------|----------------|
1290
+ | Remove | 0 |
1291
+ | 24h | 86.400 |
1292
+ | 7d | 604.800 |
1293
+ | 90d | 7.776.000 |
1294
+
1295
+ - You need to pass in **Seconds**, default is 7 days
1296
+
1297
+ ```javascript
1298
+ // turn on disappearing messages
1299
+ await sock.sendMessage(
1300
+ jid,
1301
+ // this is 1 week in seconds -- how long you want messages to appear for
1302
+ { disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL }
1303
+ )
1304
+
1305
+ // will send as a disappearing message
1306
+ await sock.sendMessage(jid, { text: 'hello' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
1307
+
1308
+ // turn off disappearing messages
1309
+ await sock.sendMessage(
1310
+ jid,
1311
+ { disappearingMessagesInChat: false }
1312
+ )
1313
+ ```
1314
+
1315
+ ## 🔎 Query Pengguna
1316
+
1317
+ ### 🔍 Cek Jika ID Ada di WhatsApp
1318
+ ```javascript
1319
+ const [result] = await sock.onWhatsApp(jid)
1320
+ if (result.exists) console.log (`${jid} exists on WhatsApp, as jid: ${result.jid}`)
1321
+ ```
1322
+
1323
+ ### 📜 Query Riwayat Chat (termasuk grup)
1324
+
1325
+ - You need to have oldest message in chat
1326
+ ```javascript
1327
+ const msg = await getOldestMessageInChat(jid)
1328
+ await sock.fetchMessageHistory(
1329
+ 50, //quantity (max: 50 per query)
1330
+ msg.key,
1331
+ msg.messageTimestamp
1332
+ )
1333
+ ```
1334
+ - Messages will be received in `messaging.history-set` event
1335
+
1336
+ ### 📣 Ambil Status
1337
+ ```javascript
1338
+ const status = await sock.fetchStatus(jid)
1339
+ console.log('status: ' + status)
1340
+ ```
1341
+
1342
+ ### 🖼️ Ambil Foto Profil (termasuk grup)
1343
+ - To get the display picture of some person/group
1344
+ ```javascript
1345
+ // for low res picture
1346
+ const ppUrl = await sock.profilePictureUrl(jid)
1347
+ console.log(ppUrl)
1348
+
1349
+ // for high res picture
1350
+ const ppUrl = await sock.profilePictureUrl(jid, 'image')
1351
+ ```
1352
+
1353
+ ### 🏷️ Ambil Profil Bisnis (deskripsi/kategori)
1354
+ ```javascript
1355
+ const profile = await sock.getBusinessProfile(jid)
1356
+ console.log('business description: ' + profile.description + ', category: ' + profile.category)
1357
+ ```
1358
+
1359
+ ### 👀 Ambil Presence Seseorang (sedang mengetik/online)
1360
+ ```javascript
1361
+ // the presence update is fetched and called here
1362
+ sock.ev.on('presence.update', console.log)
1363
+
1364
+ // request updates for a chat
1365
+ await sock.presenceSubscribe(jid)
1366
+ ```
1367
+
1368
+ ## 🧑‍💼 Mengubah Profil
1369
+
1370
+ ### 🧑‍💼 Mengubah Profil Status
1371
+ ```javascript
1372
+ await sock.updateProfileStatus('Hello World!')
1373
+ ```
1374
+ ### 🧑‍💼 Mengubah Profil Name
1375
+ ```javascript
1376
+ await sock.updateProfileName('My name')
1377
+ ```
1378
+ ### 🖼️ Ubah Foto Profil (termasuk grup)
1379
+ - To change your display picture or a group's
1380
+
1381
+ > [!NOTE]
1382
+ > Like media messages, you can pass `{ stream: Stream }` or `{ url: Url }` or `Buffer` directly, you can see more [here](https://baileys.whiskeysockets.io/types/WAMediaUpload.html)
1383
+
1384
+ ```javascript
1385
+ await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })
1386
+ ```
1387
+ ### 🗑️ Hapus Foto Profil (termasuk grup)
1388
+ ```javascript
1389
+ await sock.removeProfilePicture(jid)
1390
+ ```
1391
+
1392
+ ## 👥 Grup
1393
+
1394
+ - To change group properties you need to be admin
1395
+
1396
+ ### ➕ Buat Grup
1397
+ ```javascript
1398
+ // title & participants
1399
+ const group = await sock.groupCreate('My Fab Group', ['1234@s.whatsapp.net', '4564@s.whatsapp.net'])
1400
+ console.log('created group with id: ' + group.gid)
1401
+ await sock.sendMessage(group.id, { text: 'hello there' }) // say hello to everyone on the group
1402
+ ```
1403
+ ### ➕/➖ Tambah/Hapus atau Turunkan/Naikkan Status
1404
+ ```javascript
1405
+ // id & people to add to the group (will throw error if it fails)
1406
+ await sock.groupParticipantsUpdate(
1407
+ jid,
1408
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1409
+ 'add' // replace this parameter with 'remove' or 'demote' or 'promote'
1410
+ )
1411
+ ```
1412
+ ### ✏️ Ubah Subjek (Nama)
1413
+ ```javascript
1414
+ await sock.groupUpdateSubject(jid, 'New Subject!')
1415
+ ```
1416
+ ### 📝 Ubah Deskripsi
1417
+ ```javascript
1418
+ await sock.groupUpdateDescription(jid, 'New Description!')
1419
+ ```
1420
+ ### ⚙️ Ubah Pengaturan
1421
+ ```javascript
1422
+ // only allow admins to send messages
1423
+ await sock.groupSettingUpdate(jid, 'announcement')
1424
+ // allow everyone to send messages
1425
+ await sock.groupSettingUpdate(jid, 'not_announcement')
1426
+ // allow everyone to modify the group's settings -- like display picture etc.
1427
+ await sock.groupSettingUpdate(jid, 'unlocked')
1428
+ // only allow admins to modify the group's settings
1429
+ await sock.groupSettingUpdate(jid, 'locked')
1430
+ ```
1431
+ ### 🚪 Keluar Grup
1432
+ ```javascript
1433
+ // will throw error if it fails
1434
+ await sock.groupLeave(jid)
1435
+ ```
1436
+ ### 🔐 Dapatkan Kode Undangan
1437
+ - To create link with code use `'https://chat.whatsapp.com/' + code`
1438
+ ```javascript
1439
+ const code = await sock.groupInviteCode(jid)
1440
+ console.log('group code: ' + code)
1441
+ ```
1442
+ ### 🔄 Cabut Kode Undangan
1443
+ ```javascript
1444
+ const code = await sock.groupRevokeInvite(jid)
1445
+ console.log('New group code: ' + code)
1446
+ ```
1447
+ ### ➿ Bergabung Menggunakan Kode Undangan
1448
+ - Code can't have `https://chat.whatsapp.com/`, only code
1449
+ ```javascript
1450
+ const response = await sock.groupAcceptInvite(code)
1451
+ console.log('joined to: ' + response)
1452
+ ```
1453
+ ### ℹ️ Dapatkan Info Grup lewat Kode Undangan
1454
+ ```javascript
1455
+ const response = await sock.groupGetInviteInfo(code)
1456
+ console.log('group information: ' + response)
1457
+ ```
1458
+ ### 🔎 Query Metadata (peserta, nama, deskripsi...)
1459
+ ```javascript
1460
+ const metadata = await sock.groupMetadata(jid)
1461
+ console.log(metadata.id + ', title: ' + metadata.subject + ', description: ' + metadata.desc)
1462
+ ```
1463
+ ### Join using `groupInviteMessage`
1464
+ ```javascript
1465
+ const response = await sock.groupAcceptInviteV4(jid, groupInviteMessage)
1466
+ console.log('joined to: ' + response)
1467
+ ```
1468
+ ### 📥 Dapatkan Daftar Permintaan Bergabung
1469
+ ```javascript
1470
+ const response = await sock.groupRequestParticipantsList(jid)
1471
+ console.log(response)
1472
+ ```
1473
+ ### ✅/❌ Setuju/Tolak Permintaan Bergabung
1474
+ ```javascript
1475
+ const response = await sock.groupRequestParticipantsUpdate(
1476
+ jid, // group id
1477
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1478
+ 'approve' // or 'reject'
1479
+ )
1480
+ console.log(response)
1481
+ ```
1482
+ ### 📚 Dapatkan Semua Metadata Grup yang Diikuti
1483
+ ```javascript
1484
+ const response = await sock.groupFetchAllParticipating()
1485
+ console.log(response)
1486
+ ```
1487
+ ### ⏳ Toggle Ephemeral
1488
+
1489
+ - Ephemeral can be:
1490
+
1491
+ | Time | Seconds |
1492
+ |-------|----------------|
1493
+ | Remove | 0 |
1494
+ | 24h | 86.400 |
1495
+ | 7d | 604.800 |
1496
+ | 90d | 7.776.000 |
1497
+
1498
+ ```javascript
1499
+ await sock.groupToggleEphemeral(jid, 86400)
1500
+ ```
1501
+
1502
+ ### 🔐 Ubah Mode Penambahan
1503
+ ```javascript
1504
+ await sock.groupMemberAddMode(
1505
+ jid,
1506
+ 'all_member_add' // or 'admin_add'
1507
+ )
1508
+ ```
1509
+
1510
+ ## 🔒 Privasi
1511
+
1512
+ ### ⛔/✅ Blokir/Buka Blokir Pengguna
1513
+ ```javascript
1514
+ await sock.updateBlockStatus(jid, 'block') // Block user
1515
+ await sock.updateBlockStatus(jid, 'unblock') // Unblock user
1516
+ ```
1517
+ ### ⚙️ Dapatkan Pengaturan Privasi
1518
+ ```javascript
1519
+ const privacySettings = await sock.fetchPrivacySettings(true)
1520
+ console.log('privacy settings: ' + privacySettings)
1521
+ ```
1522
+ ### 📛 Dapatkan Daftar Blokir
1523
+ ```javascript
1524
+ const response = await sock.fetchBlocklist()
1525
+ console.log(response)
1526
+ ```
1527
+ ### 👀 Update Privasi LastSeen
1528
+ ```javascript
1529
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1530
+ await sock.updateLastSeenPrivacy(value)
1531
+ ```
1532
+ ### 🟢 Update Privasi Online
1533
+ ```javascript
1534
+ const value = 'all' // 'match_last_seen'
1535
+ await sock.updateOnlinePrivacy(value)
1536
+ ```
1537
+ ### 🖼️ Update Privasi Foto Profil
1538
+ ```javascript
1539
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1540
+ await sock.updateProfilePicturePrivacy(value)
1541
+ ```
1542
+ ### 📣 Update Privasi Status
1543
+ ```javascript
1544
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1545
+ await sock.updateStatusPrivacy(value)
1546
+ ```
1547
+ ### ✅ Update Privasi Read Receipts
1548
+ ```javascript
1549
+ const value = 'all' // 'none'
1550
+ await sock.updateReadReceiptsPrivacy(value)
1551
+ ```
1552
+ ### 👥 Update Privasi Tambah Grup
1553
+ ```javascript
1554
+ const value = 'all' // 'contacts' | 'contact_blacklist'
1555
+ await sock.updateGroupsAddPrivacy(value)
1556
+ ```
1557
+ ### 🕒 Update Mode Default Disappearing
1558
+
1559
+ - Like [this](#disappearing-messages), ephemeral can be:
1560
+
1561
+ | Time | Seconds |
1562
+ |-------|----------------|
1563
+ | Remove | 0 |
1564
+ | 24h | 86.400 |
1565
+ | 7d | 604.800 |
1566
+ | 90d | 7.776.000 |
1567
+
1568
+ ```javascript
1569
+ const ephemeral = 86400
1570
+ await sock.updateDefaultDisappearingMode(ephemeral)
1571
+ ```
1572
+
1573
+ ## 📢 Broadcast & Story
1574
+
1575
+ ### 📤 Kirim Broadcast & Story
1576
+ - Messages can be sent to broadcasts & stories. You need to add the following message options in sendMessage, like this:
1577
+ ```javascript
1578
+ await sock.sendMessage(
1579
+ jid,
1580
+ {
1581
+ image: {
1582
+ url: url
1583
+ },
1584
+ caption: caption
1585
+ },
1586
+ {
1587
+ backgroundColor: backgroundColor,
1588
+ font: font,
1589
+ statusJidList: statusJidList,
1590
+ broadcast: true
1591
+ }
1592
+ )
1593
+ ```
1594
+ - Message body can be a `extendedTextMessage` or `imageMessage` or `videoMessage` or `voiceMessage`, see [here](https://baileys.whiskeysockets.io/types/AnyRegularMessageContent.html)
1595
+ - You can add `backgroundColor` and other options in the message options, see [here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html)
1596
+ - `broadcast: true` enables broadcast mode
1597
+ - `statusJidList`: a list of people that you can get which you need to provide, which are the people who will get this status message.
1598
+
1599
+ - You can send messages to broadcast lists the same way you send messages to groups & individual chats.
1600
+ - Right now, WA Web does not support creating broadcast lists, but you can still delete them.
1601
+ - Broadcast IDs are in the format `12345678@broadcast`
1602
+ ### 🔎 Query Penerima & Nama Broadcast List
1603
+ ```javascript
1604
+ const bList = await sock.getBroadcastListInfo('1234@broadcast')
1605
+ console.log (`list name: ${bList.name}, recps: ${bList.recipients}`)
1606
+ ```
1607
+
1608
+ ## ✍️ Menulis Fungsionalitas Kustom
1609
+ Baileys is written with custom functionality in mind. Instead of forking the project & re-writing the internals, you can simply write your own extensions.
1610
+
1611
+ ### 🐛 Mengaktifkan Level Debug di Log Baileys
1612
+ First, enable the logging of unhandled messages from WhatsApp by setting:
1613
+ ```javascript
1614
+ const sock = makeWASocket({
1615
+ logger: P({ level: 'debug' }),
1616
+ })
1617
+ ```
1618
+ This will enable you to see all sorts of messages WhatsApp sends in the console.
1619
+
1620
+ ### 🔬 Bagaimana WhatsApp Berkomunikasi dengan Kita
1621
+
1622
+ > [!TIP]
1623
+ > If you want to learn whatsapp protocol, we recommend to study about Libsignal Protocol and Noise Protocol
1624
+
1625
+ - **Example:** Functionality to track the battery percentage of your phone. You enable logging and you'll see a message about your battery pop up in the console:
1626
+ ```
1627
+ {
1628
+ "level": 10,
1629
+ "fromMe": false,
1630
+ "frame": {
1631
+ "tag": "ib",
1632
+ "attrs": {
1633
+ "from": "@s.whatsapp.net"
1634
+ },
1635
+ "content": [
1636
+ {
1637
+ "tag": "edge_routing",
1638
+ "attrs": {},
1639
+ "content": [
1640
+ {
1641
+ "tag": "routing_info",
1642
+ "attrs": {},
1643
+ "content": {
1644
+ "type": "Buffer",
1645
+ "data": [8,2,8,5]
1646
+ }
1647
+ }
1648
+ ]
1649
+ }
1650
+ ]
1651
+ },
1652
+ "msg":"communication"
1653
+ }
1654
+ ```
1655
+
1656
+ The `'frame'` is what the message received is, it has three components:
1657
+ - `tag` -- what this frame is about (eg. message will have 'message')
1658
+ - `attrs` -- a string key-value pair with some metadata (contains ID of the message usually)
1659
+ - `content` -- the actual data (eg. a message node will have the actual message content in it)
1660
+ - read more about this format [here](/src/WABinary/readme.md)
1661
+
1662
+ ### 🔁 Mendaftarkan Callback untuk Event Websocket
1663
+
1664
+ > [!TIP]
1665
+ > Recommended to see `onMessageReceived` function in `socket.ts` file to understand how websockets events are fired
1666
+
1667
+ ```javascript
1668
+ // for any message with tag 'edge_routing'
1669
+ sock.ws.on('CB:edge_routing', (node: BinaryNode) => { })
1670
+
1671
+ // for any message with tag 'edge_routing' and id attribute = abcd
1672
+ sock.ws.on('CB:edge_routing,id:abcd', (node: BinaryNode) => { })
1673
+
1674
+ // for any message with tag 'edge_routing', id attribute = abcd & first content node routing_info
1675
+ sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node: BinaryNode) => { })
1676
+ ```
1677
+
1678
+ > [!NOTE]
1679
+ > Also, this repo is now licenced under GPL 3 since it uses [libsignal-node](https://git.questbook.io/backend/service-coderunner/-/merge_requests/1)
1680
+
1681
+
1682
+
1683
+ ## ⚠️ Catatan
1684
+
1685
+ Proyek ini **tidak berafiliasi dengan WhatsApp Inc.**
1686
+ Gunakan secara bertanggung jawab dan hindari aktivitas ilegal atau penyalahgunaan.
227
1687
 
228
- This project is not affiliated with WhatsApp Inc. Use it responsibly. Avoid spam, abuse, or any illegal activities.
229
- Fork baileys
1688
+ ---
230
1689
 
231
- License
1690
+ ## Lisensi
232
1691
 
233
- MIT © 2024
1692
+ 📘 *Documentation powered by jagoan project*
1693
+ 🧑‍💻 **Modified and Presented by Jagoan Project**