@xbibzlibrary/whatsbibz 1.3.0 → 1.3.2

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.id.md ADDED
@@ -0,0 +1,374 @@
1
+ <p align="center">
2
+ <img src="https://cdn.jsdelivr.net/gh/XbibzOfficial777/whatsbibz@main/assets/logo/preview.png" alt="WhatsBibz" width="360">
3
+ </p>
4
+
5
+ <h1 align="center">WhatsBibz</h1>
6
+
7
+ <p align="center">
8
+ Library WhatsApp Web multi-device untuk Node.js — fork Baileys yang dirawat, dengan klien tingkat tinggi,
9
+ pairing code kustom, sesi yang memulihkan diri sendiri, dan identitas perangkat tertaut yang bisa diatur atau dipilih otomatis.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/@xbibzlibrary/whatsbibz"><img src="https://img.shields.io/npm/v/%40xbibzlibrary%2Fwhatsbibz?label=npm&color=0a6958" alt="versi npm"></a>
14
+ <a href="https://www.npmjs.com/package/@xbibzlibrary/whatsbibz"><img src="https://img.shields.io/npm/dm/%40xbibzlibrary%2Fwhatsbibz?color=0a6958" alt="unduhan npm"></a>
15
+ <a href="https://github.com/XbibzOfficial777/whatsbibz/actions/workflows/ci.yml"><img src="https://github.com/XbibzOfficial777/whatsbibz/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
16
+ <a href="#persyaratan"><img src="https://img.shields.io/badge/node-%E2%89%A5%2020-0a6958" alt="Node.js >= 20"></a>
17
+ <a href="LICENSE"><img src="https://img.shields.io/badge/lisensi-MIT-0a6958" alt="MIT"></a>
18
+ </p>
19
+
20
+ <p align="center">
21
+ <a href="README.md">English</a> · <b>Bahasa Indonesia</b>
22
+ </p>
23
+
24
+ ---
25
+
26
+ ## Daftar isi
27
+
28
+ - [Mengapa WhatsBibz](#mengapa-whatsbibz)
29
+ - [Persyaratan](#persyaratan)
30
+ - [Instalasi](#instalasi)
31
+ - [Mulai cepat](#mulai-cepat)
32
+ - [Klien tingkat tinggi: `createBibzWhats()`](#klien-tingkat-tinggi-createbibzwhats)
33
+ - [Opsi](#opsi)
34
+ - [Event](#event)
35
+ - [Properti dan metode](#properti-dan-metode)
36
+ - [Siklus hidup koneksi](#siklus-hidup-koneksi)
37
+ - [Identitas perangkat tertaut](#identitas-perangkat-tertaut)
38
+ - [Mode otomatis (bawaan)](#mode-otomatis-bawaan)
39
+ - [Mode kustom](#mode-kustom)
40
+ - [Apa yang diterima WhatsApp](#apa-yang-diterima-whatsapp)
41
+ - [Mengirim dan membaca pesan](#mengirim-dan-membaca-pesan)
42
+ - [API tingkat rendah (kompatibel Baileys)](#api-tingkat-rendah-kompatibel-baileys)
43
+ - [TypeScript](#typescript)
44
+ - [Migrasi dari Baileys / ourin-baileys](#migrasi-dari-baileys--ourin-baileys)
45
+ - [Pemecahan masalah](#pemecahan-masalah)
46
+ - [Pengujian](#pengujian)
47
+ - [Struktur proyek](#struktur-proyek)
48
+ - [Versi dan kompatibilitas](#versi-dan-kompatibilitas)
49
+ - [Berkontribusi](#berkontribusi)
50
+ - [Keamanan](#keamanan)
51
+ - [Lisensi](#lisensi)
52
+
53
+ ## Mengapa WhatsBibz
54
+
55
+ WhatsBibz adalah fork penuh dari [Baileys](https://github.com/WhiskeySockets/Baileys) v7 (lewat `ourin-baileys@9.0.21`), sudah di-patch sampai `master` upstream saat ini, ditambah lapisan yang menyelesaikan hal-hal yang selalu ditulis ulang oleh setiap pembuat bot:
56
+
57
+ | Masalah | Yang dilakukan WhatsBibz |
58
+ |---|---|
59
+ | Pairing "berhasil" tetapi HP tidak pernah menampilkan notifikasi | `requestPairingCode()` menunggu pengakuan server. Penolakan (`400`, `429`) dan timeout muncul sebagai error, bukan sukses palsu. |
60
+ | Nama perangkat tertaut ditolak server (`428` sebelum QR, `400` saat pairing) | Identitas **bisa diatur** (`identity: 'archLinux:Chrome'`) atau **otomatis**: profil paling stabil dipakai lebih dulu dan klien berpindah ke profil berikutnya hanya bila server menolak. Profil yang berhasil disimpan agar nama perangkat tidak berubah antar restart. |
61
+ | Sesi korup atau ter-logout berputar tanpa henti | `401 / 500 / 411 / korup` → folder sesi dihapus, kredensial baru, pairing ulang — dibatasi `maxSessionWipes`. |
62
+ | Notifikasi `companion_reg_refresh` mematikan sesi yang belum tertaut | Ditangani di dalam socket (tanpa patch `postinstall`). |
63
+ | Timer bocor setelah `close()`, reconnect "hantu" | `close()` membatalkan semua reconnect terjadwal; diverifikasi 40 siklus create→close. |
64
+ | Pengguna TypeScript mendapat `WAProto/index.d.ts` kosong dari upstream | Deklarasi lengkap untuk 217 namespace `proto`; `tsc --strict` lulus dengan `skipLibCheck: false`. |
65
+
66
+ Semua ekspor Baileys tetap ada — kode lama tetap berjalan, cukup ganti specifier import-nya.
67
+
68
+ ## Persyaratan
69
+
70
+ - **Node.js ≥ 20** (diuji di 20, 22, 24, dan 26)
71
+ - Hanya ESM (`"type": "module"` atau `import()` dinamis)
72
+ - Peer opsional: `sharp` (thumbnail media), `qrcode-terminal` (QR ASCII), `link-preview-js`, `jimp`, `audio-decode`, `@roamhq/wrtc` (VoIP)
73
+
74
+ ## Instalasi
75
+
76
+ ```bash
77
+ npm install @xbibzlibrary/whatsbibz
78
+ ```
79
+
80
+ ## Mulai cepat
81
+
82
+ ```js
83
+ import { createBibzWhats, extractMessage, sendText } from '@xbibzlibrary/whatsbibz';
84
+
85
+ const client = await createBibzWhats({
86
+ phone: '6281234567890', // nomor bot, digit dengan kode negara
87
+ pairingCode: 'XBIBZPRO', // opsional: kode kustom 8 karakter (A–Z, 0–9)
88
+ authDir: 'whatsbibz-session',
89
+ });
90
+
91
+ client.on('pairing-code', (code) => console.log('Masukkan kode ini di HP:', code));
92
+
93
+ client.on('ready', (sock) => {
94
+ sock.ev.on('messages.upsert', async ({ messages, type }) => {
95
+ if (type !== 'notify') return;
96
+ for (const m of messages) {
97
+ if (m.key.fromMe) continue;
98
+ const item = extractMessage(m);
99
+ if (item?.type === 'text' && /^ping$/i.test(item.text)) {
100
+ await sendText(sock, m.key.remoteJid, 'pong', { quoted: m });
101
+ }
102
+ }
103
+ });
104
+ });
105
+ ```
106
+
107
+ Di HP: **Setelan → Perangkat tertaut → Tautkan perangkat → Tautkan dengan nomor telepon**, lalu ketik kodenya. Kosongkan `phone` untuk memakai QR (`client.on('qr', ...)`, atau `printQR: true` untuk mencetaknya di terminal).
108
+
109
+ Contoh yang bisa langsung dijalankan ada di [`example/ping-bot.js`](example/ping-bot.js).
110
+
111
+ ## Klien tingkat tinggi: `createBibzWhats()`
112
+
113
+ `createBibzWhats(options)` mengembalikan Promise berisi klien berbasis `EventEmitter` yang mengelola socket untukmu: mengambil versi WhatsApp Web terkini, menentukan identitas perangkat, meminta pairing code, menyambung ulang dengan back-off, menghapus sesi rusak, dan pairing ulang.
114
+
115
+ ### Opsi
116
+
117
+ | Opsi | Tipe | Bawaan | Keterangan |
118
+ |---|---|---|---|
119
+ | `phone` | `string` | — | Nomor bot, digit dengan kode negara. Wajib untuk pairing code; kosongkan untuk QR. |
120
+ | `pairingCode` | `string` | acak | Kode kustom, tepat 8 karakter `A–Z0–9`. Bila server menolak kode kustom, klien memakai kode acak sekali. |
121
+ | `authDir` | `string` | `'bibzwhats-session'` | Folder kredensial, kunci signal, dan `identity.json`. |
122
+ | `identity` | `'auto' \| string \| [os, browser, versi]` | `'auto'` | Identitas perangkat tertaut. Lihat [Identitas perangkat tertaut](#identitas-perangkat-tertaut). |
123
+ | `browser` | `[os, browser, versi]` | `null` | Alias lama `identity` (tuple eksplisit). |
124
+ | `maxIdentityRotations` | `number` | `4` | Mode otomatis: jumlah profil alternatif yang dicoba sebelum menyerah. |
125
+ | `companionPlatformDisplay` | `string \| null` | `null` | Override `companion_platform_display` saat pairing. Isi hanya bila kamu yakin nilainya ada di allow-list WhatsApp. |
126
+ | `logger` | `{ info, warn, error, debug, ok }` | console | Objek apa pun dengan metode tersebut (semua opsional). |
127
+ | `printQR` | `boolean` | `false` | Cetak QR sebagai ASCII saat QR ditampilkan (butuh `qrcode-terminal`). |
128
+ | `socketConfig` | `Partial<SocketConfig>` | `{}` | Opsi mentah `makeWASocket`, digabung paling akhir — pintu keluar penuh. |
129
+ | `fetchLatestVersion` | `boolean` | `true` | Ambil versi WhatsApp Web terkini di setiap connect. Versi bawaan tidak pernah diturunkan. |
130
+ | `forceIPv4` | `boolean` | `true` | Paksa IPv4 untuk unggah media. |
131
+ | `readyOnEveryConnect` | `boolean` | `true` | Pancarkan `ready` untuk setiap socket baru (connect pertama dan tiap reconnect). |
132
+ | `maxReconnectAttempts` | `number` | `10` | Reconnect gagal berturut-turut sebelum `give-up`. |
133
+ | `reconnectStepMs` / `reconnectMaxMs` | `number` | `10000` / `60000` | Back-off linear: `step × percobaan`, maksimum `max`. |
134
+ | `restartDelayMs` | `number` | `2000` | Jeda setelah `515 restartRequired` (normal setelah pairing) dan setelah rotasi identitas. |
135
+ | `maxSessionWipes` | `number` | `3` | Penghapusan sesi (401/500/411/korup) sebelum `give-up`. |
136
+ | `wipeReconnectDelayMs` | `number` | `10000` | Jeda sebelum menyambung ulang dengan kredensial baru. |
137
+ | `qrFallbackAfterMs` | `number` | `90000` | Dengan `phone` terisi, tampilkan QR bila tidak ada pairing code yang diterima dalam waktu ini. |
138
+ | `pairingRequestDelayMs` | `number` | `20000` | Bila server tidak mengirim QR sama sekali, minta pairing code langsung setelah jeda ini. |
139
+ | `groupMetadataTtlMs` | `number` | `300000` | TTL cache metadata grup saat mengirim ke grup. |
140
+
141
+ Nilai bawaan diekspor sebagai `BIBZWHATS_DEFAULTS`.
142
+
143
+ ### Event
144
+
145
+ | Event | Payload | Kapan |
146
+ |---|---|---|
147
+ | `pairing-code` | `(code, { custom, fallback })` | Server menerima permintaan pairing code. `custom` = kodemu dipakai; `fallback` = server menolak kode kustom dan menerbitkan kode acak. |
148
+ | `qr` | `(qr)` | String QR tersedia (langsung tanpa `phone`, atau setelah `qrFallbackAfterMs`). |
149
+ | `ready` | `(sock)` | **Socket baru** siap. Pasang handler pesan di sini — socket diganti saat reconnect dan listener lama ikut mati. |
150
+ | `first-ready` | `(sock)` | Seperti `ready`, tetapi hanya sekali seumur klien. |
151
+ | `open` | `(sock)` | Koneksi terbuka (setiap kali). |
152
+ | `user` | `(digits)` | Nomor bot sendiri diketahui. |
153
+ | `close` | `({ status, error })` | Koneksi tertutup. `status` adalah kode `DisconnectReason`. |
154
+ | `reconnecting` | `({ delay, attempt, fresh, identity?, pairingPending? })` | Reconnect dijadwalkan. `fresh` = dengan kredensial baru; `identity` = profil setelah rotasi; `pairingPending` = pairing sebelumnya masih tertunda di server (lihat siklus hidup). |
155
+ | `identity-changed` | `({ browser, linkedDeviceName, pairingDisplay, pairingDisplayAccepted, profileId, reason })` | Hanya mode otomatis: server menolak profil sebelumnya dan profil berikutnya dipakai. |
156
+ | `session-wiped` | `(reason)` | Folder sesi dihapus (`'401 loggedOut'`, `'500 badSession'`, `'411'`, `'sesi korup'`, `'401 pairing tertunda'`). |
157
+ | `give-up` | `(message)` | Klien berhenti mencoba. Perlu campur tangan manusia (nomor salah, IP diblokir, …). |
158
+ | `connection.update` | `(update)` | Update koneksi mentah Baileys, diteruskan apa adanya. |
159
+
160
+ ### Properti dan metode
161
+
162
+ | Anggota | Keterangan |
163
+ |---|---|
164
+ | `client.sock` | Socket saat ini (`null` sebelum connect pertama; berubah saat reconnect). |
165
+ | `client.identity` | `{ mode: 'auto' \| 'custom', source, profileId, browser, linkedDeviceName, pairingDisplay, pairingDisplayAccepted, tried: [{ id, reason }] }` |
166
+ | `client.options` | Opsi efektif setelah nilai bawaan. |
167
+ | `client.isConnected()` | `true` selama socket terbuka. |
168
+ | `client.close()` | Tutup socket dan batalkan reconnect terjadwal. Tidak meninggalkan timer. |
169
+ | `client.logout()` | Logout perangkat di server dan hapus folder sesi. |
170
+
171
+ ### Siklus hidup koneksi
172
+
173
+ ```
174
+ connect ──► QR / pairing code ──► 515 restartRequired ──► reconnect (2 dtk) ──► open ──► ready
175
+ │ │
176
+ │ 428 sebelum QR / 405 (identitas ditolak) auto → profil berikutnya, 2 dtk │ putus jaringan → 1 dtk, lalu back-off
177
+ │ 400 saat pairing (identitas ditolak) auto → profil berikutnya, 2 dtk │ 401 sudah terdaftar → hapus sesi, pairing ulang
178
+ │ 401 dengan pairing tertunda kredensial baru, 2 dtk │
179
+ └─ kode close lain ── back-off 10 dtk × percobaan (maks 60 dtk, 10 percobaan) ── give-up
180
+ ```
181
+
182
+ Yang perlu diketahui:
183
+
184
+ - **515 setelah pairing itu normal.** Server meminta klien restart; klien menyambung ulang setelah `restartDelayMs`.
185
+ - **401 dengan pairing tertunda.** Bila koneksi putus tepat setelah pairing code terbit, server menjawab connect berikutnya dengan `401`. Ini bukan nomor salah: klien mengganti kredensial dan meminta kode baru dalam 2 detik. Jalur ini tidak dihitung ke `maxSessionWipes`.
186
+ - **Rotasi identitas hanya terjadi sebelum perangkat terdaftar.** Setelah tertaut, identitas dikunci — mengubahnya akan terlihat sebagai perangkat lain di HP.
187
+ - **Penghapusan sesi mempertahankan `identity.json`** bila identitasnya sudah diterima (`qr-received`, `pairing-accepted`, `open`), sehingga nama perangkat tetap sama setelah pairing ulang.
188
+
189
+ ## Identitas perangkat tertaut
190
+
191
+ Tuple `browser = [os, browser, versi]` menentukan apa yang tampil di HP pada **Perangkat tertaut**, dan sebagiannya divalidasi WhatsApp saat pairing.
192
+
193
+ ### Mode otomatis (bawaan)
194
+
195
+ ```js
196
+ const client = await createBibzWhats({ phone }); // identity: 'auto'
197
+ client.on('identity-changed', (i) => console.log('pindah ke', i.linkedDeviceName, 'karena', i.reason));
198
+ console.log(client.identity);
199
+ // { mode: 'auto', profileId: 'macos-chrome', linkedDeviceName: 'Chrome (Mac OS)',
200
+ // pairingDisplay: 'Chrome (Mac OS)', pairingDisplayAccepted: true, tried: [] }
201
+ ```
202
+
203
+ Klien mulai dari profil dengan rekam jejak terbaik dan berpindah hanya pada sinyal penolakan (`428` sebelum QR, `400 bad-request` saat pairing, `405`):
204
+
205
+ | Urutan | Profil | Tampil di HP | Dikirim saat pairing |
206
+ |---|---|---|---|
207
+ | 1 | `macos-chrome` | Chrome (Mac OS) | Chrome (Mac OS) |
208
+ | 2 | `macos-safari` | Safari (Mac OS) | Safari (Mac OS) |
209
+ | 3 | `windows-chrome` | Chrome (Windows) | Chrome (Windows) |
210
+ | 4 | `linux-chrome` | Chrome (Linux) | Chrome (Linux) |
211
+ | 5 | `ubuntu-chrome` | Chrome (Ubuntu) | Chrome (Ubuntu) |
212
+ | 6 | `macos-firefox` | Firefox (Mac OS) | Firefox (Mac OS) |
213
+ | 7 | `windows-edge` | Edge (Windows) | Edge (Windows) |
214
+ | 8 | `archlinux-chrome` | Chrome (Arch Linux) | Chrome (Linux) |
215
+
216
+ Profil yang berhasil ditulis ke `<authDir>/identity.json` dan dipakai lagi pada start berikutnya. Hapus file itu (atau seluruh `authDir`) untuk memulai dari awal.
217
+
218
+ ### Mode kustom
219
+
220
+ Identitas kustom dipakai **apa adanya** dan tidak pernah diganti diam-diam. Bila server menolaknya, kamu mendapat error yang jelas di log, bukan nama perangkat yang berbeda.
221
+
222
+ ```js
223
+ createBibzWhats({ phone, identity: Browsers.archLinux('Chrome') }); // tuple preset
224
+ createBibzWhats({ phone, identity: ['Arch Linux', 'Firefox', '6.16.4'] }); // tuple bebas
225
+ createBibzWhats({ phone, identity: 'archLinux:Firefox' }); // "preset:Browser"
226
+ createBibzWhats({ phone, identity: 'Mac OS/Safari/15.6.1' }); // "OS/Browser/Versi"
227
+ createBibzWhats({ phone, identity: 'linux-chrome' }); // id profil
228
+ createBibzWhats({ phone, browser: ['Mac OS', 'Chrome', '14.4.1'] }); // alias lama
229
+ ```
230
+
231
+ Variabel lingkungan bekerja tanpa mengubah kode — prioritas: opsi → env → otomatis:
232
+
233
+ ```bash
234
+ BIBZ_BROWSER="archLinux:Chrome" # atau "Arch Linux/Firefox/6.16", atau "auto"
235
+ # atau trio
236
+ BIBZ_DEVICE_OS="Arch Linux" BIBZ_DEVICE_BROWSER="Chrome" BIBZ_DEVICE_VERSION="6.16"
237
+ ```
238
+
239
+ Versi kosong diisi per OS (Mac OS `15.6.1`, Windows `10.0.22631`, Linux `6.12.44`, lainnya `1.0.0`).
240
+
241
+ Preset di `Browsers`: `macOS`, `windows`, `ubuntu`, `linux`, `archLinux`, `android` (eksperimental), `appropriate` (mengikuti OS host, mengenali distro lewat `/etc/os-release`), `whatsbibz`.
242
+
243
+ ### Apa yang diterima WhatsApp
244
+
245
+ Identitas dipakai di tiga tempat dengan aturan berbeda. Diukur terhadap server produksi pada 2026-09-03:
246
+
247
+ | Tempat | Dipakai untuk | Aturan server | Perilaku WhatsBibz |
248
+ |---|---|---|---|
249
+ | `DeviceProps.os` (`browser[0]`) | Teks di *Perangkat tertaut* | Teks bebas | Dikirim apa adanya — "Arch Linux" tampil sebagai "Arch Linux" |
250
+ | `companion_platform_display` (pairing code) | Validasi permintaan pairing | **Allow-list**; nilai tak dikenal → `400`, HP tidak pernah dapat notifikasi | Diturunkan otomatis ke nilai valid (`derivePairingDisplay`): Arch Linux → `Chrome (Linux)` |
251
+ | `WebInfo.webSubPlatform` (`Desktop` + `syncFullHistory`) | Jenis klien desktop | `DARWIN` / `APP_STORE` ditutup (`428` sebelum QR); `WIN_HYBRID` / `WEB_BROWSER` berfungsi | Mac OS Desktop → `WEB_BROWSER`, riwayat penuh tetap diminta |
252
+
253
+ | Diterima | Ditolak (`400`) |
254
+ |---|---|
255
+ | OS: Mac OS, macOS, Windows, Linux, Ubuntu, Debian, Fedora, CentOS, Gentoo, Manjaro, Chromium OS, Android, iOS | OS: Arch Linux, Arch, GNU/Linux, Mac OS X, Linux Mint, openSUSE, Kali, NixOS, Pop!_OS, FreeBSD, Chrome OS, nama produk apa pun |
256
+ | Browser: Chrome, Chromium, Firefox, Safari, Edge, Opera, Brave, Vivaldi, Arc | Browser: Desktop, nama produk apa pun |
257
+
258
+ Helper: `derivePairingDisplay(browser)`, `isPairingDisplayAccepted(str)`, `lintIdentity({ browser, companionPlatformDisplay })`, `resolveDeviceIdentity(opts)`, `parseBrowserSpec(spec)`, `identityFromEnv(env)`, `describeIdentity(browser)`, `IDENTITY_PROFILES`.
259
+
260
+ ## Mengirim dan membaca pesan
261
+
262
+ ```js
263
+ import {
264
+ sendText, sendMedia, react, presence, sendWithRetry, splitText, whatsappify,
265
+ extractMessage, unwrapMessage, messageTimestampMs,
266
+ LidMap, digitsOf, pnJid, lidJid, isGroupJid, isLidJid, sameUser, normalizeJid,
267
+ } from '@xbibzlibrary/whatsbibz';
268
+ ```
269
+
270
+ | Helper | Fungsi |
271
+ |---|---|
272
+ | `sendText(sock, jid, text, { quoted, format, maxLen })` | Memecah teks panjang (≤ 4000 karakter per pesan), retry 3×, mengubah Markdown ke format WhatsApp bila `format: true`. Mengembalikan `{ ok, ids, error? }`. |
273
+ | `sendMedia(sock, jid, content, { quoted, fallbackToDocument })` | Mengirim gambar/video/audio/dokumen; bila media ditolak, dikirim ulang sebagai dokumen. |
274
+ | `react(sock, jid, key, emoji)` | Memberi reaksi pada pesan. |
275
+ | `presence(sock, jid, state)` | `composing`, `recording`, `paused`, `available`, `unavailable`. |
276
+ | `sendWithRetry(sock, jid, content, options, { attempts })` | `sendMessage` generik dengan retry. |
277
+ | `extractMessage(m)` | Menormalkan pesan masuk apa pun menjadi `{ type, text, participant, mentions, quoted, imageMsg \| videoMsg \| … , buttonId, pollName, … }`. Membuka pembungkus ephemeral, view-once, dan pesan yang diedit. |
278
+ | `LidMap` | Memetakan JID LID ↔ nomor: `learnFromMessage(m)`, `canonical(jid)`, `variants(jid)`, `toJSON()` / `fromJSON()`. |
279
+
280
+ `sock.sendMessage(jid, content)` mentah mendukung semua yang didukung Baileys: teks, gambar, video, audio, dokumen, stiker, paket stiker, lokasi, kontak, polling, reaksi, edit, hapus, pin, teruskan, view-once, tombol interaktif, pesan produk dan event, newsletter. Builder `Button`, `Carousel`, dan `AIRich` diekspor.
281
+
282
+ ## API tingkat rendah (kompatibel Baileys)
283
+
284
+ ```js
285
+ import makeWASocket, {
286
+ useMultiFileAuthState, makeCacheableSignalKeyStore, fetchLatestWaWebVersion,
287
+ DisconnectReason, Browsers, downloadMediaMessage, proto, jidNormalizedUser,
288
+ } from '@xbibzlibrary/whatsbibz';
289
+
290
+ const { state, saveCreds } = await useMultiFileAuthState('session');
291
+ const { version } = await fetchLatestWaWebVersion();
292
+ const sock = makeWASocket({ version, auth: state, browser: Browsers.macOS('Chrome') });
293
+ sock.ev.on('creds.update', saveCreds);
294
+ ```
295
+
296
+ Semua yang ada di Baileys v7 / ourin-baileys diekspor dengan nama yang sama. Penggantian nama: `Dugong` → `BibzWhatsEngine`, `sock.ourin` → `sock.bibz` (`sock.ourin` dipertahankan sebagai alias). Opsi socket tambahan: `companionPlatformDisplay`, `companionPlatformId`, `webSubPlatform`.
297
+
298
+ Tambahan di atas `master` upstream (sumber ada di [CHANGELOG.md](CHANGELOG.md)): `WIN32 → WIN_HYBRID` untuk Windows Desktop, `requestPairingCode` lewat `query()` dengan `creds.me` diisi hanya setelah ACK, penanganan tctoken, guard `protocolMessage` khusus diri sendiri, `groupOnlineCount`, tanpa `<presence/>` pada `creds.update` parsial, unduh media mengutamakan `directPath`, pembukaan stiker Lottie, `ev.destroy()` / `signalRepository.close()` saat socket berakhir, `whatsapp-rust-bridge` 0.5.5.
299
+
300
+ ## TypeScript
301
+
302
+ Deklarasi tipe ikut dalam paket, termasuk `WAProto/index.d.ts` yang lengkap. Diverifikasi dengan `tsc --strict`, `moduleResolution: NodeNext`, dan `skipLibCheck: false`; satu-satunya tambahan yang dibutuhkan adalah `@types/node`.
303
+
304
+ ```ts
305
+ import { createBibzWhats, type BibzWhatsClient, type ResolvedIdentity } from '@xbibzlibrary/whatsbibz';
306
+
307
+ const client: BibzWhatsClient = await createBibzWhats({ phone: '628…', identity: 'archLinux:Chrome' });
308
+ client.on('identity-changed', (i) => console.log(i.linkedDeviceName));
309
+ ```
310
+
311
+ ## Migrasi dari Baileys / ourin-baileys
312
+
313
+ 1. `npm uninstall baileys ourin-baileys && npm install @xbibzlibrary/whatsbibz`
314
+ 2. Ganti specifier import. Semua ekspor mempertahankan namanya.
315
+ 3. Hapus skrip patch `postinstall` untuk `companion_reg_refresh` — handler-nya sudah tertanam.
316
+ 4. Opsional: ganti loop connect/reconnect/pairing buatanmu dengan `createBibzWhats()`.
317
+
318
+ ## Pemecahan masalah
319
+
320
+ | Gejala | Penyebab | Solusi |
321
+ |---|---|---|
322
+ | Pairing code tercetak, HP tidak menampilkan apa pun | Library lama mencetak kode sebelum server mengonfirmasi. WhatsBibz hanya memancarkan `pairing-code` setelah ACK — bila tetap tidak muncul, nomornya salah atau IP dibatasi. | Periksa digitnya (kode negara, tanpa `+`, tanpa `0` di depan). Tunggu 15 menit bila kamu mencoba berkali-kali (`429`). |
323
+ | `428` seketika, tanpa QR | Identitas yang diiklankan ditolak (mis. sub-platform `DARWIN`). | Biarkan `identity` kosong (otomatis berputar), atau pilih profil dari tabel di atas. |
324
+ | `400 bad-request` saat pairing | `companion_platform_display` tidak ada di allow-list. | Jangan override `companionPlatformDisplay`; nilai turunannya selalu valid. |
325
+ | `401` tepat setelah reconnect saat pairing | Pairing sebelumnya masih tertunda di server. | Ditangani otomatis (`reconnecting` dengan `pairingPending: true`). |
326
+ | Loop `408` | Versi WhatsApp Web terlalu lama. | Pertahankan `fetchLatestVersion: true` (bawaan) atau perbarui paket. |
327
+ | `give-up` setelah 3 kali hapus sesi | Bukan masalah sesi: nomor tidak terdaftar, digit salah, atau IP diblokir. | Pastikan nomor aktif di WhatsApp; coba jaringan lain. |
328
+ | Handler berhenti bekerja setelah reconnect | Handler dipasang di socket lama. | Pasang di dalam `client.on('ready', sock => …)`. |
329
+ | Proses tidak mau keluar | Ada hal lain yang menahan event loop — klien tidak meninggalkan timer setelah `close()`. | Periksa interval buatanmu; panggil `client.close()` sebelum `process.exit`. |
330
+
331
+ ## Pengujian
332
+
333
+ ```bash
334
+ npm test # 55 test offline (protokol, identitas, pairing controller, siklus hidup) — tanpa jaringan
335
+ npm run check # pemeriksaan permukaan ekspor
336
+ npm run test:live # 11 test ke server WhatsApp sungguhan (tanpa HP; memakai nomor fiktif Ofcom)
337
+ ```
338
+
339
+ Suite live mencakup QR, pengakuan pairing, rotasi otomatis pada `428` dan `400`, identitas kustom, kontrol negatif, dan pemutusan jaringan paksa. Hasil lengkap: [VERIFIKASI-IDENTITAS-2026-09-03.md](VERIFIKASI-IDENTITAS-2026-09-03.md).
340
+
341
+ ## Struktur proyek
342
+
343
+ ```
344
+ lib/
345
+ BibzWhats/ client.js (createBibzWhats), device-identity.js, pairing.js, send.js, extract.js, jid.js
346
+ Socket/ socket.js, engine.js, messages-send.js, messages-recv.js, groups.js, newsletter.js, ...
347
+ Utils/ platform-identity.js, browser-utils.js, messages-media.js, use-multi-file-auth-state.js, ...
348
+ Defaults/ Signal/ Types/ WABinary/ WAM/ WAUSync/ VoIP/ Modded/
349
+ WAProto/ definisi protobuf (index.js + index.d.ts lengkap)
350
+ assets/logo/ logo, ikon, favicon
351
+ example/ ping-bot.js
352
+ test/ suite node:test (offline + live)
353
+ ```
354
+
355
+ ## Versi dan kompatibilitas
356
+
357
+ - Semantic versioning. Perubahan yang memutus kompatibilitas hanya di rilis mayor.
358
+ - Versi WhatsApp Web bawaan diperbarui di setiap rilis dan diambil langsung di setiap connect.
359
+ - Node.js yang didukung: jalur LTS saat ini dan rilis terbaru (20 / 22 / 24 / 26 saat ini ditulis).
360
+ - Perubahan dicatat di [CHANGELOG.md](CHANGELOG.md).
361
+
362
+ ## Berkontribusi
363
+
364
+ Laporan bug, hasil pengukuran terhadap server WhatsApp, dan pull request diterima. Baca [CONTRIBUTING.md](CONTRIBUTING.md) lebih dulu — di sana dijelaskan syarat pengujian dan cara menjalankan suite live dengan aman. Setiap orang yang berpartisipasi diharapkan mengikuti [Kode Etik](CODE_OF_CONDUCT.md).
365
+
366
+ ## Keamanan
367
+
368
+ Jangan buka issue publik untuk kerentanan. Lihat [SECURITY.md](SECURITY.md).
369
+
370
+ ## Lisensi
371
+
372
+ MIT — © 2026 Xbibz Developer. Berbasis Baileys, MIT © Rajeh Taher / WhiskeySockets — lihat [LICENSE](LICENSE) dan [LICENSE.upstream](LICENSE.upstream).
373
+
374
+ WhatsBibz tidak berafiliasi dengan, didukung oleh, atau disokong oleh WhatsApp maupun Meta. Gunakan nomor khusus, patuhi Ketentuan Layanan WhatsApp, dan jangan mengirim pesan yang tidak diminta.