sauruspro-bail 5.0.2 β†’ 5.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,318 @@
1
+ <div align="center">
2
+
3
+ # πŸ¦– SAURUSPRO BAILEYS
4
+
5
+ **WhatsApp Web API untuk Node.js, lengkap dengan Rich Message, SPR, dan Newsletter Status**
6
+
7
+ <img src="https://cdn.saurus.qzz.io/image/EGYoX.png" width="140" alt="Sauruspro">
8
+
9
+ ![npm](https://img.shields.io/npm/v/sauruspro-bail?style=for-the-badge&color=8b5cf6)
10
+ ![downloads](https://img.shields.io/npm/dt/sauruspro-bail?style=for-the-badge&color=c084fc)
11
+ ![node](https://img.shields.io/badge/Node.js-20%2B-22c55e?style=for-the-badge)
12
+ ![license](https://img.shields.io/badge/License-MIT-3b82f6?style=for-the-badge)
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ ## πŸ“– Apa itu Baileys?
19
+
20
+ **Baileys** adalah library JavaScript/TypeScript yang berbicara langsung dengan server WhatsApp lewat **WebSocket**, sama seperti WhatsApp Web, tetapi **tanpa browser** dan tanpa Selenium/Puppeteer. Dengan Baileys kamu bisa membuat bot atau aplikasi yang:
21
+
22
+ - login sebagai *linked device* (perangkat tertaut) lewat **QR** atau **pairing code**,
23
+ - mengirim dan menerima pesan (teks, gambar, video, stiker, poll, dll),
24
+ - mengelola grup, komunitas, channel (newsletter), dan profil,
25
+ - berjalan ringan karena hanya memakai protokol multi-device, bukan emulasi browser.
26
+
27
+ **Sauruspro Baileys (`sauruspro-bail`)** adalah turunan Baileys dengan fitur tambahan:
28
+
29
+ | Fitur | Isi |
30
+ |---|---|
31
+ | πŸ’¬ **Rich Message** | `AIRich`, Carousel, Button, Native Flow, A2UI |
32
+ | 🎯 **SPR (Selective Relay)** | Kirim pesan hanya ke device tertentu, pesan khusus per orang |
33
+ | πŸ“’ **Newsletter Status** | Kirim, react, hapus, dan ambil status Channel |
34
+ | πŸͺͺ **Greeting Card `/buss`** | Kartu sapaan untuk WhatsApp Business |
35
+ | 🧩 **Plugin system** | `sock.use(plugin)` dan fitur bawaan bisa dimatikan |
36
+ | πŸ‘€ **Presence & Profile API** | `sock.presence.*` dan `sock.profile.*` yang lebih rapi |
37
+ | ⚑ **Native crypto (opsional)** | X25519 dan XEdDSA lebih cepat jika `@zapo-js/native` terpasang |
38
+
39
+ > Beberapa fitur diadaptasi dari [zapo-js](https://github.com/vinikjkkj/zapo) (MIT).
40
+
41
+ ## πŸ“¦ Info Paket
42
+
43
+ | | |
44
+ |---|---|
45
+ | Nama | `sauruspro-bail` |
46
+ | Modul | ESM (`"type": "module"`), bisa dipakai dari CommonJS (lihat di bawah) |
47
+ | Node.js | >= 20 |
48
+ | Telegram | [@lordsaurus](https://t.me/lordsaurus) |
49
+
50
+ ## πŸš€ Install
51
+
52
+ ```bash
53
+ npm install sauruspro-bail
54
+ ```
55
+
56
+ ---
57
+
58
+ ## πŸ”Œ Menghubungkan ke WhatsApp (bot)
59
+
60
+ Ada dua cara login: **QR code** atau **pairing code** (kode 8 karakter yang dimasukkan di HP). Sesi disimpan di folder, jadi login hanya perlu sekali.
61
+
62
+ ### Contoh lengkap (pairing code + reconnect)
63
+
64
+ ```js
65
+ import makeWASocket, {
66
+ useMultiFileAuthState,
67
+ DisconnectReason,
68
+ Browsers
69
+ } from 'sauruspro-bail'
70
+
71
+ const NOMOR = '628123456789' // format internasional, tanpa +, spasi, atau strip
72
+
73
+ async function start() {
74
+ const { state, saveCreds } = await useMultiFileAuthState('session')
75
+
76
+ const sock = makeWASocket({
77
+ auth: state,
78
+ browser: Browsers.ubuntu('Chrome') // dianjurkan untuk pairing code
79
+ })
80
+
81
+ // simpan kredensial setiap kali berubah
82
+ sock.ev.on('creds.update', saveCreds)
83
+
84
+ // minta pairing code hanya jika belum login
85
+ if (!sock.authState.creds.registered) {
86
+ const code = await sock.requestPairingCode(NOMOR)
87
+ console.log('Pairing code:', code.match(/.{1,4}/g).join('-'))
88
+ // HP: WhatsApp > Perangkat tertaut > Tautkan perangkat > Tautkan dengan nomor telepon
89
+ }
90
+
91
+ // status koneksi + reconnect otomatis
92
+ sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
93
+ if (connection === 'open') console.log('βœ… Bot terhubung')
94
+ if (connection === 'close') {
95
+ const status = lastDisconnect?.error?.output?.statusCode
96
+ if (status === DisconnectReason.loggedOut) {
97
+ console.log('Logout. Hapus folder "session" lalu jalankan ulang.')
98
+ } else {
99
+ start() // koneksi putus, sambungkan lagi
100
+ }
101
+ }
102
+ })
103
+
104
+ // contoh membalas pesan
105
+ sock.ev.on('messages.upsert', async ({ messages }) => {
106
+ const msg = messages[0]
107
+ if (!msg?.message || msg.key.fromMe) return
108
+ const teks = msg.message.conversation || msg.message.extendedTextMessage?.text
109
+ if (teks === 'ping') {
110
+ await sock.sendMessage(msg.key.remoteJid, { text: 'pong' }, { quoted: msg })
111
+ }
112
+ })
113
+ }
114
+
115
+ start()
116
+ ```
117
+
118
+ ### Catatan pairing code
119
+
120
+ - Setiap pemanggilan `requestPairingCode` menghasilkan **kode acak baru**. Kamu juga bisa memakai kode sendiri: `requestPairingCode(NOMOR, 'ABCD1234')` (8 karakter, `A-Z` dan `0-9`).
121
+ - Nomor otomatis dibersihkan, jadi `+62 812-3456-789` tetap diterima.
122
+ - Jika sesi sudah login (`registered`), pairing ditolak. Hapus folder sesi untuk login ulang.
123
+ - Kode berlaku singkat. Kalau kedaluwarsa, panggil `requestPairingCode` lagi.
124
+
125
+ ### Login dengan QR
126
+
127
+ Dengarkan event `connection.update` dan tampilkan `qr` (misalnya dengan paket `qrcode-terminal`):
128
+
129
+ ```js
130
+ sock.ev.on('connection.update', ({ qr }) => {
131
+ if (qr) console.log('Scan QR ini di WhatsApp:', qr)
132
+ })
133
+ ```
134
+
135
+ ### Menyimpan sesi di SQLite (opsional)
136
+
137
+ ```js
138
+ import { useSqliteAuthState } from 'sauruspro-bail'
139
+ const { state, saveCreds } = await useSqliteAuthState('session.db')
140
+ ```
141
+
142
+ ---
143
+
144
+ ## πŸ“œ Memakai dari CommonJS (`require`)
145
+
146
+ Paket ini ESM. Dari file `.js`/`.cjs` biasa, ada dua cara:
147
+
148
+ **1. `import()` dinamis (semua versi Node 20+, paling aman)**
149
+
150
+ ```js
151
+ // index.cjs
152
+ async function main() {
153
+ const { default: makeWASocket, useMultiFileAuthState } = await import('sauruspro-bail')
154
+
155
+ const { state, saveCreds } = await useMultiFileAuthState('session')
156
+ const sock = makeWASocket({ auth: state })
157
+ sock.ev.on('creds.update', saveCreds)
158
+ }
159
+ main()
160
+ ```
161
+
162
+ **2. `require()` langsung (Node 22.12+ atau Node 20.19+)**
163
+
164
+ ```js
165
+ const baileys = require('sauruspro-bail')
166
+ const makeWASocket = baileys.default
167
+ const { useMultiFileAuthState } = baileys
168
+ ```
169
+
170
+ Pada Node versi lama, `require('sauruspro-bail')` akan error `ERR_REQUIRE_ESM`. Pakai cara pertama.
171
+
172
+ Mau ubah proyekmu jadi ESM saja? Tambahkan `"type": "module"` di `package.json` proyekmu lalu pakai `import`.
173
+
174
+ ---
175
+
176
+ ## πŸ’¬ Rich Message (AIRich)
177
+
178
+ Rich Message adalah balasan bergaya Meta AI: teks, kode, tabel, gambar, dan lainnya dalam satu pesan. Dibuat dengan builder `sock.AIRich`.
179
+
180
+ ```js
181
+ const rich = new sock.AIRich(sock)
182
+
183
+ rich
184
+ .addText('Halo! Ini **Rich Message** dari Sauruspro.')
185
+ .addCode('javascript', "console.log('halo dunia')")
186
+ .addTable([
187
+ ['Fitur', 'Status'],
188
+ ['SPR', 'Aktif'],
189
+ ['Newsletter Status', 'Aktif']
190
+ ])
191
+
192
+ await rich.send(jid)
193
+ ```
194
+
195
+ Cara singkat tanpa builder:
196
+
197
+ ```js
198
+ import { sendAIRichMessage } from 'sauruspro-bail'
199
+
200
+ await sendAIRichMessage(sock, jid, { text: 'Halo dari Rich Message!' })
201
+ ```
202
+
203
+ Builder lain yang tersedia: `sock.Carousel`, `sock.Button`, `sock.ButtonV2`, `sock.Toolkit`. Pesan `interactiveMessage`, `buttonsMessage`, `flowMessage`, dan `carouselMessage` juga bisa dikirim lewat `sock.sendMessage`.
204
+
205
+ > Rich Message memakai fitur WhatsApp yang bisa berubah. Tampilannya bergantung pada versi aplikasi penerima.
206
+
207
+ ---
208
+
209
+ ## 🎯 SPR (Selective Relay)
210
+
211
+ SPR mengontrol **siapa membaca apa** dalam satu pesan grup. Tiap device penerima masuk salah satu peran:
212
+
213
+ | Peran | Yang diterima |
214
+ |---|---|
215
+ | `public` | pesan umum |
216
+ | `personal` | pesan khusus miliknya saja |
217
+ | `hidden` | tidak menerima apa-apa |
218
+
219
+ ```js
220
+ // Sembunyikan pesan dari 1 orang
221
+ await sock.sPR(groupJid, { conversation: 'rahasia' }, {
222
+ mode: 'exclude', // 'include' = hanya target yang menerima
223
+ target: ['6281234567890@s.whatsapp.net']
224
+ })
225
+
226
+ // Pesan umum untuk semua, pesan lain khusus untuk A
227
+ await sock.sPR(groupJid, { conversation: 'info umum' }, {
228
+ personal: { '6281234567890@s.whatsapp.net': { conversation: 'info khusus kamu' } }
229
+ })
230
+
231
+ // Anggota lain lihat publicText, targetJid lihat privateText + foto profilnya
232
+ await sock.sPRPrivate(groupJid, targetJid, {
233
+ publicText: 'Pesan ini memiliki isi khusus untuk beberapa penerima.',
234
+ privateText: 'rahasia buat kamu'
235
+ })
236
+
237
+ // Tiap anggota menerima pesan sendiri, {name} menjadi @mention orang itu
238
+ await sock.sPRBroadcast(groupJid, { template: 'Halo {name}, ada pesan untukmu.', limit: 100 })
239
+ ```
240
+
241
+ Opsi lengkap dan penjelasan lebih dalam: **[docs/SPR.md](docs/SPR.md)**
242
+
243
+ ---
244
+
245
+ ## πŸ“’ Newsletter Status
246
+
247
+ Kirim status ke **Channel (newsletter)** yang kamu admin-i. JID channel berakhiran `@newsletter`.
248
+
249
+ ```js
250
+ const jid = '120363xxxxxxxxxxxxx@newsletter'
251
+
252
+ // Teks
253
+ const sent = await sock.newsletter.sendStatus(jid, { text: 'Halo Channel!' })
254
+ console.log(sent.newsletterStatusServerId) // dipakai untuk react / revoke
255
+
256
+ // Gambar atau video
257
+ await sock.newsletter.sendStatus(jid, {
258
+ image: { url: './foto.jpg' },
259
+ caption: 'Update terbaru'
260
+ })
261
+
262
+ // React ke status
263
+ await sock.newsletter.reactToStatus(jid, sent.newsletterStatusServerId, 'πŸ”₯')
264
+
265
+ // Hapus status
266
+ await sock.newsletter.revokeStatus(jid, statusId)
267
+
268
+ // Ambil daftar status
269
+ const list = await sock.newsletter.fetchStatuses(jid, { count: 20 })
270
+ ```
271
+
272
+ Semua fungsi juga tersedia langsung di socket: `sock.sendNewsletterStatus(...)`, `sock.sendNewsletterStatusReaction(...)`, dan seterusnya.
273
+
274
+ Dokumentasi jenis konten, opsi, dan error: lihat tipe di `lib/Utils/newsletter-status.d.ts`.
275
+
276
+ ---
277
+
278
+ ## 🧩 Fitur lain
279
+
280
+ ```js
281
+ // Greeting Card /buss (hanya terlihat di WhatsApp Business)
282
+ await sock.sendGreetingCard(jid, {
283
+ text: 'wow', title: 'Judul Kartu', greeting: 'Hi Business',
284
+ imageUrl: 'https://.../img.jpg', contactUrl: 'https://wa.me/NOMOR'
285
+ })
286
+
287
+ // Presence & profile
288
+ await sock.presence.withTyping(jid, () => sock.sendMessage(jid, { text: 'halo' }))
289
+ await sock.profile.setStatus('Bot aktif')
290
+
291
+ // Plugin
292
+ import { definePlugin } from 'sauruspro-bail'
293
+ sock.use(definePlugin({ id: 'halo', setup: ({ extend }) => extend({ halo: () => 'hai' }) }))
294
+ // matikan fitur bawaan: makeWASocket({ disablePlugins: ['greeting-card'] })
295
+ ```
296
+
297
+ ## πŸ“š Dokumentasi
298
+
299
+ | File | Isi |
300
+ |---|---|
301
+ | [docs/SPR.md](docs/SPR.md) | Selective Relay lengkap |
302
+ | [docs/CHANGELOG.md](docs/CHANGELOG.md) | Riwayat versi |
303
+
304
+ ## ⚠️ Disclaimer
305
+
306
+ Library ini tidak berafiliasi dengan WhatsApp/Meta. Gunakan dengan bijak dan patuhi Terms of Service WhatsApp. Pengguna bertanggung jawab atas penggunaannya.
307
+
308
+ ## πŸ’» Developer
309
+
310
+ <div align="center">
311
+
312
+ **Saurus / Dinonic**
313
+
314
+ Telegram [@lordsaurus](https://t.me/lordsaurus)
315
+
316
+ Made with ❀️ by Saurus / Dinonic
317
+
318
+ </div>
package/docs/CHANGELOG.md CHANGED
@@ -1,64 +1,61 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.0.3
4
+ ### Fixed
5
+ - **Pair code**: `requestPairingCode` diperbaiki.
6
+ - Nomor dibersihkan otomatis (`+62 812-3456-789` menjadi `628123456789`) dan divalidasi 7-15 digit.
7
+ - Menunggu socket terbuka dulu sebelum mengirim permintaan (tidak lagi error "Connection Closed" kalau dipanggil terlalu cepat).
8
+ - Setiap request membuat kode acak baru **dan** keypair ephemeral baru (sebelumnya keypair lama dipakai ulang).
9
+ - Kode custom dinormalkan ke huruf besar dan divalidasi `A-Z0-9` 8 karakter.
10
+ - Sesi yang sudah `registered` ditolak dengan pesan jelas.
11
+ - Jika pengiriman gagal, state pairing (kode, keypair, `me`) dikembalikan seperti semula.
12
+
13
+ ### Changed
14
+ - Versi di banner `lib/index.js` kini dibaca dari `package.json` (export `packageVersion`). Banner bisa dimatikan dengan env `SAURUS_NO_BANNER=1`.
15
+ - Info fitur di banner diperbarui.
16
+ - README baru: pengertian Baileys, koneksi (QR dan pairing code), pemakaian dari CommonJS, Rich Message, SPR, dan Newsletter Status.
17
+
3
18
  ## 5.0.2
4
19
  ### Added (dari zapo-js, MIT)
5
20
  - **Greeting Card `/buss`**: `sock.sendGreetingCard(jid, { text, title, greeting, imageUrl, contactUrl, thumbnail?, sourceApp?, ref?, mentions?, adReply? }, sendOptions?)` dan `sock.buildGreetingCard(opts)`.
6
21
  Pesan `extendedTextMessage` + `contextInfo.externalAdReply`; `sourceId`, `ctwaClid`, `ctaPayload` diacak tiap kirim. Kartu hanya tampil di WhatsApp Business; user biasa hanya melihat teks.
7
- Contoh:
8
22
  ```js
9
23
  await sock.sendGreetingCard(jid, {
10
24
  text: 'wow', title: 'Megumin Dominada BUSI', greeting: 'Hi Business',
11
25
  imageUrl: 'https://.../img.jpg', contactUrl: 'https://wa.me/NOMOR'
12
26
  }, { quoted: null })
13
27
  ```
14
- - **Group History Bundle** (`sock.GroupHistory`, juga export `Utils`): `encodeGroupHistoryBundle`, `decodeGroupHistoryBundle`, `streamGroupHistoryBundle` (baca per pesan, hemat memori).
15
- - **Meta AI Bot helpers** (`sock.MetaAIBot`, juga `Utils.MetaAIBot`): `BOT_KNOWN_JIDS`, `genBotMsgSecret`, `deriveBotChunkKey`, `decryptBotChunk`, `attachBotMetadata`, `attachBotThread`, `extractInvokedBotJid`, `buildBotInvokeProtoCopy`.
16
- - **Plugin system** (dari zapo-js): `sock.use(plugin)`, `sock.removePlugin(id)`, `sock.hasPlugin(id)`, `sock.listPlugins()`, helper `definePlugin({ id, exposeAs?, setup(ctx), dispose? })`.
17
- `ctx` berisi `sock`, `config`, `logger`, `ev`, `on/off`, `registerDispose`, `extend({...})` (member yang ditambah otomatis dicabut saat plugin dihapus). Opsi socket: `plugins: [...]`, `disablePlugins: ['spr', ...]`.
18
- Fitur bawaan sekarang berupa plugin: `spr`, `greeting-card`, `group-history`, `meta-ai-bot`, `presence`, `profile` (API tetap sama; bisa dimatikan lewat `disablePlugins`).
19
- ```js
20
- const myPlugin = definePlugin({ id: 'halo', setup: ({ extend }) => extend({ halo: () => 'hai' }) })
21
- sock.use(myPlugin)
22
- ```
23
- - **Presence & Profile API**: `sock.presence` (`setOnline`, `setOffline`, `typing`, `recording`, `paused`, `subscribe`, `typeFor(jid, ms)`, `withTyping(jid, fn)`) dan `sock.profile` (`getPicture`, `setPicture`, `removePicture`, `getStatus`, `setStatus`, `setName`, `username.{get,set,delete,check,recommendations,setPin,find}`). Pembungkus dari fungsi socket yang sudah ada.
24
- - **Akselerator kripto native opsional**: jika `@zapo-js/native` terpasang, X25519 dan XEdDSA (sign/verify) dipakai lewat native (NAPI lalu WASM); tanpa paket itu otomatis tetap JS (libsignal). Env `SAURUS_NATIVE_BACKEND` = `auto|napi|wasm|js|none`. Util: `isNativeCryptoActive()`.
28
+ - **Group History Bundle** (`sock.GroupHistory`): `encodeGroupHistoryBundle`, `decodeGroupHistoryBundle`, `streamGroupHistoryBundle`.
29
+ - **Meta AI Bot helpers** (`sock.MetaAIBot`): `BOT_KNOWN_JIDS`, `genBotMsgSecret`, `deriveBotChunkKey`, `decryptBotChunk`, `attachBotMetadata`, `attachBotThread`, `extractInvokedBotJid`, `buildBotInvokeProtoCopy`.
30
+ - **Plugin system**: `sock.use(plugin)`, `sock.removePlugin(id)`, `sock.hasPlugin(id)`, `sock.listPlugins()`, helper `definePlugin({ id, exposeAs?, setup(ctx), dispose? })`. Opsi socket `plugins: [...]` dan `disablePlugins: [...]`.
31
+ Fitur bawaan berupa plugin: `spr`, `greeting-card`, `group-history`, `meta-ai-bot`, `presence`, `profile`.
32
+ - **Presence & Profile API**: `sock.presence` (`setOnline`, `setOffline`, `typing`, `recording`, `paused`, `subscribe`, `typeFor`, `withTyping`) dan `sock.profile` (`getPicture`, `setPicture`, `removePicture`, `getStatus`, `setStatus`, `setName`, `username.*`).
33
+ - **Akselerator kripto native opsional**: jika `@zapo-js/native` terpasang, X25519 dan XEdDSA memakai native (NAPI lalu WASM), jika tidak tetap JS. Env `SAURUS_NATIVE_BACKEND=auto|napi|wasm|js|none`.
34
+ - **SPR**: opsi `personal` (pesan khusus per orang), `sPRPrivate`, `sPRBroadcast` (`{name}` + mention + foto profil), `getSPRTargets`, `loadSPRAvatars`, batas target 100 dengan hitungan overflow, cache foto, budget/timeout, konkurensi (diadaptasi dari plugin zapo-js).
25
35
 
26
36
  ### Fixed
27
- - `requestPairingCode`: kode pairing tanpa custom kini acak tiap request (sebelumnya selalu `VINXSYNC`).
37
+ - Kode pairing tanpa custom kini acak tiap request (sebelumnya selalu sama).
28
38
 
29
39
  ### Changed
30
- - `lib/Utils/dinonic-spr.js` ditulis ulang dari nol (engine baru, sender key sekali pakai). API `sPR` / `selectiveRelay` tetap kompatibel.
31
-
32
- ### Added (diadaptasi dari plugin zapo-js, MIT)
33
- - Opsi `personal` pada `sPR`: pesan khusus per orang.
34
- - `sPRPrivate`, `sPRBroadcast` (`{name}` + mention + foto profil), `getSPRTargets`, `loadSPRAvatars`.
35
- - Batas target 100 + hitung overflow, cache foto, budget/timeout, konkurensi.
40
+ - `lib/Utils/dinonic-spr.js` ditulis ulang (sender key sekali pakai). API `sPR` / `selectiveRelay` tetap kompatibel.
36
41
  - Reporting token memakai util resmi, tctoken memakai pengecekan expired.
37
42
 
38
43
  ## 5.0.1
39
- **Owner: Saurus / Dinonic**
40
-
41
- ### Added (fitur tambahan, by Saurus)
44
+ ### Added
42
45
  - **A2UI / Bloks widget**: `a2uiText`, `a2uiButton`, `a2uiCard`, `a2uiTabs`, `a2uiModal`, dll, plus `sendA2UI`, `sendBloksWidget`.
43
- - **DinonicBuilder** (`sock.DinonicBuilder`): Button, ButtonV2, Carousel, AIRich, Toolkit.
44
- - **Extras / AIRich lengkap**, **HTML App** (`sendHtmlApp`, `sendHtmlDocument`), **Meta AI sections**, **Bot Signature**, **Native Flow**.
46
+ - **Builder** (`sock.DinonicBuilder`): Button, ButtonV2, Carousel, AIRich, Toolkit.
47
+ - **AIRich lengkap**, **HTML App** (`sendHtmlApp`, `sendHtmlDocument`), **Meta AI sections**, **Bot Signature**, **Native Flow**.
45
48
  - **Modern Messages**: komentar, event invite, pertanyaan/jawaban, poll add option, scheduled call, undangan newsletter, status mention/reaction/audience.
46
- - **Payment Messages** (payment reminder, split payment), **Scheduled Message** (conditional reveal), **Status Stickers** (musik, link, lokasi, pesan, channel).
47
- - **Dinonic handler** (`Socket/dinonic-handler.js`): Interactive/Carousel, Buttons, Flow, Group Story di `sendMessage`, plus `sock.sendStatusWhatsApp` dan `sock.getName`.
49
+ - **Payment Messages** (payment reminder, split payment), **Scheduled Message**, **Status Stickers** (musik, link, lokasi, pesan, channel).
50
+ - Handler `Socket/dinonic-handler.js`: Interactive/Carousel, Buttons, Flow, Group Story di `sendMessage`, plus `sock.sendStatusWhatsApp` dan `sock.getName`.
48
51
  - Opsi socket: `rejectCalls`, `callRejectMessage`, `autoReadStatus`, `autoReadMessages`.
49
- - `baileys-event-stream`, file `.d.ts` untuk modul baru.
52
+ - `baileys-event-stream` dan file `.d.ts` untuk modul baru.
50
53
 
51
54
  ### Changed
52
- - Semua nama `dinolith` β†’ `dinonic` (termasuk file `dinonic-spr.js`). Branding fitur tambahan diganti menjadi Saurus / Dinonic.
53
55
  - **Newsletter Status** diganti dengan implementasi penuh (alias `prepareNewsletterStatusContent` dan `makeNewsletterStatusAttribution` tetap ada).
54
- - Pesan `interactiveMessage`, `buttonsMessage`, `flowMessage`, `carouselMessage`/`cards` sekarang lewat handler Dinonic.
55
-
56
- ### Tidak dibawa
57
- - Telegram adapter dan bridge, auto-follow channel (sudah ada di `Socket/newsletter.js`), registrasi mobile, mobile client, `phonenumber-mcc` (dasar Baileys lama).
56
+ - Pesan `interactiveMessage`, `buttonsMessage`, `flowMessage`, `carouselMessage`/`cards` sekarang lewat handler baru.
58
57
 
59
58
  ## 5.0.0
60
- **Owner: Saurus / Dinonic**
61
-
62
59
  ### Added
63
60
  - **Newsletter Status**: `sendNewsletterStatus`, `sendNewsletterStatusReaction`, `revokeNewsletterStatus`, `getNewsletterStatuses`, `getNewsletterStatusUpdates`, plus `sock.newsletter.{sendStatus, reactToStatus, revokeStatus, fetchStatuses, fetchStatusUpdates}`.
64
61
  - File tipe `newsletter-status.d.ts` dan `dinonic-spr.d.ts`.
@@ -67,12 +64,4 @@
67
64
 
68
65
  ### Fixed
69
66
  - `dinonic-spr.js` mengimpor `encodeSignedDeviceIdentity` dari `generics.js` (tidak ada), sehingga seluruh paket gagal load. Sekarang dari `validate-connection.js`.
70
- - SPR: disamakan penuh dengan SPR diezyxhao-baileys 1.4.0 (logika identik, hanya CJS β†’ ESM), termasuk fallback `conn.user` saat `authState.creds.me` kosong.
71
- - `package.json`: `"type": "module"` ditambahkan (kode ESM), duplikat `lru-cache` di devDependencies dihapus.
72
-
73
- ### Changed
74
- - Versi `3.0.0` β†’ `5.0.0`, author/owner `Saurus / Dinonic`.
75
- - README ditulis ulang, banner menampilkan versi & owner.
76
-
77
- ### Notes
78
- - Newsletter status diport dari diezyxhao-baileys 1.4.0 ke ESM; tidak mengubah `sendMessage`.
67
+ - SPR: fallback `conn.user` saat `authState.creds.me` kosong.
@@ -735,63 +735,92 @@ export const makeSocket = (config) => {
735
735
  void end(new Boom(msg || 'Intentional Logout', { statusCode: DisconnectReason.loggedOut }));
736
736
  };
737
737
  const requestPairingCode = async (phoneNumber, customPairingCode) => {
738
- if (customPairingCode && customPairingCode.length !== 8) {
739
- throw new Error('Custom pairing code must be exactly 8 chars');
738
+ if (authState.creds.registered) {
739
+ throw new Boom('Sesi sudah terdaftar (registered). Hapus folder sesi untuk pairing ulang.', { statusCode: 400 });
740
740
  }
741
- // Tanpa kode custom: generate acak (Crockford base32) tiap request, bukan konstanta tetap.
742
- const pairingCode = customPairingCode ?? bytesToCrockford(randomBytes(5));
743
- authState.creds.pairingCode = pairingCode;
741
+ // Nomor harus angka saja dengan kode negara (tanpa +, spasi, atau strip).
742
+ const digits = String(phoneNumber ?? '').replace(/\D/g, '');
743
+ if (digits.length < 7 || digits.length > 15) {
744
+ throw new Boom('Nomor tidak valid. Gunakan format internasional tanpa +, contoh: 628123456789', { statusCode: 400 });
745
+ }
746
+ let customCode;
747
+ if (customPairingCode) {
748
+ customCode = String(customPairingCode).toUpperCase();
749
+ if (!/^[A-Z0-9]{8}$/.test(customCode)) {
750
+ throw new Error('Custom pairing code must be exactly 8 chars (A-Z, 0-9)');
751
+ }
752
+ }
753
+ // Pastikan koneksi sudah terbuka sebelum mengirim permintaan pairing.
754
+ await waitForSocketOpen();
755
+ const previous = {
756
+ pairingCode: authState.creds.pairingCode,
757
+ pairingEphemeralKeyPair: authState.creds.pairingEphemeralKeyPair,
758
+ me: authState.creds.me
759
+ };
760
+ // Kode acak baru + keypair ephemeral baru di setiap request (tidak memakai ulang yang lama).
761
+ authState.creds.pairingCode = customCode ?? bytesToCrockford(randomBytes(5));
762
+ authState.creds.pairingEphemeralKeyPair = Curve.generateKeyPair();
744
763
  authState.creds.me = {
745
- id: jidEncode(phoneNumber, 's.whatsapp.net'),
764
+ id: jidEncode(digits, 's.whatsapp.net'),
746
765
  name: '~'
747
766
  };
748
767
  ev.emit('creds.update', authState.creds);
749
- await sendNode({
750
- tag: 'iq',
751
- attrs: {
752
- to: S_WHATSAPP_NET,
753
- type: 'set',
754
- id: generateMessageTag(),
755
- xmlns: 'md'
756
- },
757
- content: [
758
- {
759
- tag: 'link_code_companion_reg',
760
- attrs: {
761
- jid: authState.creds.me.id,
762
- stage: 'companion_hello',
763
- should_show_push_notification: 'true'
764
- },
765
- content: [
766
- {
767
- tag: 'link_code_pairing_wrapped_companion_ephemeral_pub',
768
- attrs: {},
769
- content: await generatePairingKey()
770
- },
771
- {
772
- tag: 'companion_server_auth_key_pub',
773
- attrs: {},
774
- content: authState.creds.noiseKey.public
775
- },
776
- {
777
- tag: 'companion_platform_id',
778
- attrs: {},
779
- content: getCompanionPlatformId(browser)
780
- },
781
- {
782
- tag: 'companion_platform_display',
783
- attrs: {},
784
- content: `${browser[1]} (${browser[0]})`
768
+ try {
769
+ await sendNode({
770
+ tag: 'iq',
771
+ attrs: {
772
+ to: S_WHATSAPP_NET,
773
+ type: 'set',
774
+ id: generateMessageTag(),
775
+ xmlns: 'md'
776
+ },
777
+ content: [
778
+ {
779
+ tag: 'link_code_companion_reg',
780
+ attrs: {
781
+ jid: authState.creds.me.id,
782
+ stage: 'companion_hello',
783
+ should_show_push_notification: 'true'
785
784
  },
786
- {
787
- tag: 'link_code_pairing_nonce',
788
- attrs: {},
789
- content: '0'
790
- }
791
- ]
792
- }
793
- ]
794
- });
785
+ content: [
786
+ {
787
+ tag: 'link_code_pairing_wrapped_companion_ephemeral_pub',
788
+ attrs: {},
789
+ content: await generatePairingKey()
790
+ },
791
+ {
792
+ tag: 'companion_server_auth_key_pub',
793
+ attrs: {},
794
+ content: authState.creds.noiseKey.public
795
+ },
796
+ {
797
+ tag: 'companion_platform_id',
798
+ attrs: {},
799
+ content: getCompanionPlatformId(browser)
800
+ },
801
+ {
802
+ tag: 'companion_platform_display',
803
+ attrs: {},
804
+ content: `${browser[1]} (${browser[0]})`
805
+ },
806
+ {
807
+ tag: 'link_code_pairing_nonce',
808
+ attrs: {},
809
+ content: '0'
810
+ }
811
+ ]
812
+ }
813
+ ]
814
+ });
815
+ }
816
+ catch (error) {
817
+ // Gagal kirim: kembalikan state lama supaya tidak tertinggal kode/keypair setengah jadi.
818
+ authState.creds.pairingCode = previous.pairingCode;
819
+ authState.creds.pairingEphemeralKeyPair = previous.pairingEphemeralKeyPair;
820
+ authState.creds.me = previous.me;
821
+ ev.emit('creds.update', authState.creds);
822
+ throw error;
823
+ }
795
824
  return authState.creds.pairingCode;
796
825
  };
797
826
  async function generatePairingKey() {
package/lib/index.js CHANGED
@@ -1,5 +1,10 @@
1
1
  import makeWASocket from './Socket/index.js';
2
2
  import chalk from "chalk";
3
+ import { createRequire } from "module";
4
+
5
+ const require = createRequire(import.meta.url);
6
+ // Versi diambil dari package.json supaya selalu sinkron.
7
+ export const packageVersion = require("../package.json").version;
3
8
 
4
9
  const ascii = [
5
10
  "β €β €β €β €β’€β‘ β €β ”β’²β’Άβ‘–β ’β €β’„β‘€β €β €β €β €β €β €β €β €β €",
@@ -22,13 +27,16 @@ const ascii = [
22
27
  const info = [
23
28
  { label: "", value: "Baileys Saurus Pro", title: true },
24
29
  { label: "", value: "" },
25
- { label: "✦", value: "Custom Baileys Socket" },
26
- { label: "✦", value: "Custom Pairing Support" },
27
- { label: "✦", value: "Rich Message Support" },
30
+ { label: "✦", value: "Pairing Code & QR (kode acak, sudah diperbaiki)" },
31
+ { label: "✦", value: "Rich Message (AIRich, Carousel, Button)" },
28
32
  { label: "✦", value: "SPR (Selective Relay)" },
29
33
  { label: "✦", value: "Newsletter Status" },
34
+ { label: "✦", value: "Greeting Card /buss" },
35
+ { label: "✦", value: "Plugin System (sock.use)" },
36
+ { label: "✦", value: "Presence & Profile API" },
37
+ { label: "✦", value: "Native Crypto (opsional)" },
30
38
  { label: "", value: "" },
31
- { label: "Version", value: "v5.0.1" },
39
+ { label: "Version", value: `v${packageVersion}` },
32
40
  { label: "Owner", value: "Saurus / Dinonic" },
33
41
  { label: "Telegram", value: "t.me/lordsaurus" },
34
42
  { label: "WA Owner", value: "+62 895-6390-43495" }
@@ -45,6 +53,7 @@ const infoLines = info.map(({ label, value, title }) => {
45
53
  });
46
54
 
47
55
  const rows = Math.max(ascii.length, infoLines.length);
56
+ if (!process.env.SAURUS_NO_BANNER) {
48
57
  console.log("\n");
49
58
  for (let i = 0; i < rows; i++) {
50
59
  const art = ascii[i] || "".padEnd(24);
@@ -52,6 +61,7 @@ for (let i = 0; i < rows; i++) {
52
61
  console.log(" " + purple(art) + " " + text);
53
62
  }
54
63
  console.log("\n");
64
+ }
55
65
  export * from '../WAProto/index.js';
56
66
  export * from './Utils/index.js';
57
67
  export * from './Types/index.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sauruspro-bail",
3
- "version": "5.0.2",
4
- "description": "Sauruspro Baileys - Custom WhatsApp Web API with SPR (Selective Relay), Newsletter Status, Rich Messages and pairing support.",
3
+ "version": "5.0.3",
4
+ "description": "Sauruspro Baileys - WhatsApp Web API (Baileys) dengan SPR (Selective Relay), Newsletter Status, Rich Messages, Greeting Card, plugin system, dan pairing code.",
5
5
  "keywords": [
6
6
  "baileys",
7
7
  "whatsapp",