@xbibzlibrary/whatsbibz 1.3.1 → 1.4.0

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/SECURITY.md ADDED
@@ -0,0 +1,91 @@
1
+ # Security Policy
2
+
3
+ *Bahasa Indonesia di bawah / Indonesian version below.*
4
+
5
+ ## Supported versions
6
+
7
+ | Version | Supported |
8
+ |---|---|
9
+ | 1.3.x | Yes |
10
+ | < 1.3 | No — please upgrade |
11
+
12
+ Only the latest minor release receives security fixes.
13
+
14
+ ## Reporting a vulnerability
15
+
16
+ **Please do not open a public issue for security problems.**
17
+
18
+ Report privately by one of these channels:
19
+
20
+ - GitHub: **Security → Report a vulnerability** on this repository (private advisory).
21
+ - Email: **revandoppratama@gmail.com** with the subject `[whatsbibz security]`.
22
+
23
+ Include:
24
+
25
+ - A description of the issue and its impact.
26
+ - Steps or a script to reproduce it.
27
+ - The package version (`npm ls @xbibzlibrary/whatsbibz`) and Node.js version.
28
+ - Whether the issue requires a paired session, network position, or a malicious remote peer.
29
+
30
+ You will get an acknowledgement within **3 business days** and a status update at least every **7 days** until the issue is resolved. When a fix is released you will be credited in the changelog unless you prefer otherwise.
31
+
32
+ ## What counts as a vulnerability here
33
+
34
+ - Anything that lets a **remote WhatsApp peer** (a contact, a group member, a newsletter) execute code, crash the process, corrupt local state or read data it should not — for example through a crafted `protocolMessage`, media metadata or app-state patch.
35
+ - Leakage of session material (`creds.json`, signal keys, `identity.json`) through logs, error messages or file permissions.
36
+ - Weaknesses in the pairing or Noise handshake handling that were introduced by this fork.
37
+ - Dependency vulnerabilities that are reachable from this package's code paths.
38
+
39
+ Out of scope: WhatsApp server behaviour, account bans, rate limits, and issues in the upstream Baileys project that are not reachable through WhatsBibz (please report those upstream).
40
+
41
+ ## Handling secrets safely
42
+
43
+ - Session folders contain long-lived credentials. Keep them outside the repository, with restrictive permissions, and never share them.
44
+ - Rotate your credentials (`client.logout()` and re-pair) if a session folder may have leaked.
45
+ - Do not paste `creds.json`, pairing codes for real numbers, or tokens into issues.
46
+
47
+ ---
48
+
49
+ # Kebijakan Keamanan
50
+
51
+ ## Versi yang didukung
52
+
53
+ | Versi | Didukung |
54
+ |---|---|
55
+ | 1.3.x | Ya |
56
+ | < 1.3 | Tidak — silakan perbarui |
57
+
58
+ Hanya rilis minor terbaru yang menerima perbaikan keamanan.
59
+
60
+ ## Melaporkan kerentanan
61
+
62
+ **Jangan membuka issue publik untuk masalah keamanan.**
63
+
64
+ Laporkan secara pribadi lewat salah satu jalur berikut:
65
+
66
+ - GitHub: **Security → Report a vulnerability** di repositori ini (advisory privat).
67
+ - Email: **revandoppratama@gmail.com** dengan subjek `[whatsbibz security]`.
68
+
69
+ Sertakan:
70
+
71
+ - Deskripsi masalah dan dampaknya.
72
+ - Langkah atau skrip untuk mereproduksinya.
73
+ - Versi paket (`npm ls @xbibzlibrary/whatsbibz`) dan versi Node.js.
74
+ - Apakah masalah memerlukan sesi yang sudah tertaut, posisi jaringan tertentu, atau lawan bicara jarak jauh yang berniat jahat.
75
+
76
+ Kamu akan menerima konfirmasi dalam **3 hari kerja** dan pembaruan status setidaknya setiap **7 hari** sampai masalah selesai. Saat perbaikan dirilis, namamu dicantumkan di changelog kecuali kamu meminta sebaliknya.
77
+
78
+ ## Yang dianggap kerentanan di sini
79
+
80
+ - Apa pun yang memungkinkan **peer WhatsApp jarak jauh** (kontak, anggota grup, newsletter) mengeksekusi kode, membuat proses crash, merusak state lokal, atau membaca data yang seharusnya tidak bisa — misalnya lewat `protocolMessage`, metadata media, atau patch app-state yang direkayasa.
81
+ - Kebocoran materi sesi (`creds.json`, kunci signal, `identity.json`) lewat log, pesan error, atau izin berkas.
82
+ - Kelemahan dalam penanganan pairing atau handshake Noise yang diperkenalkan oleh fork ini.
83
+ - Kerentanan dependensi yang dapat dijangkau dari jalur kode paket ini.
84
+
85
+ Di luar cakupan: perilaku server WhatsApp, pemblokiran akun, batas laju, dan masalah di proyek upstream Baileys yang tidak dapat dijangkau lewat WhatsBibz (silakan laporkan ke upstream).
86
+
87
+ ## Menjaga rahasia dengan aman
88
+
89
+ - Folder sesi berisi kredensial berumur panjang. Simpan di luar repositori, dengan izin terbatas, dan jangan pernah dibagikan.
90
+ - Rotasi kredensialmu (`client.logout()` lalu pairing ulang) bila folder sesi mungkin bocor.
91
+ - Jangan menempelkan `creds.json`, pairing code untuk nomor sungguhan, atau token ke dalam issue.
@@ -1,21 +1,19 @@
1
1
  # Logo WhatsBibz
2
2
 
3
- Gelembung pesan hijau (`#0a6958`) dengan buku terbuka di dalamnya, wordmark **WhatsBib'S** dan
4
- tagline *WHATSAPP LIBRARY*. Sumber utamanya adalah `preview-2048.png` (raster 2048×2048, dari
5
- pemilik proyek); semua berkas lain diturunkan dari situ.
3
+ Logo utama (banner/logo lebar 1672×940) diberikan oleh pemilik proyek sebagai WebP
4
+ dan disimpan sebagai `preview.webp`; turunan PNG-nya ada di `preview.png`.
5
+ Keduanya dipakai untuk README dan halaman npm.
6
6
 
7
7
  | Berkas | Pakai untuk |
8
8
  |---|---|
9
- | `preview.png` | lockup lengkap 1024×1024 — README, halaman npm, dokumen |
10
- | `preview-2048.png` | master resolusi penuh (tidak ikut dipublish ke npm) |
11
- | `png/logo-1600.png`, `png/logo-800.png` | lockup dipangkas rapi (tanpa margin besar) |
12
- | `png/mark-1024.png`, `png/mark-512.png` | gelembung saja, **latar transparan** — avatar, watermark |
13
- | `png/icon-{16…1024}.png` | ikon persegi sudut membulat (tile putih + gelembung) — avatar npm/GitHub, app icon |
9
+ | `preview.webp` | master asli (WebP 1672×940) — README, halaman npm |
10
+ | `preview.png` | versi PNG `preview.webp` (1080×607) |
11
+ | `preview-2048.png` | master persegi 2048×2048 dari rebrand sebelumnya (arsip) |
12
+ | `png/logo-1600.png`, `png/logo-800.png` | lockup lama yang dipangkas rapi |
13
+ | `png/mark-1024.png`, `png/mark-512.png` | gelembung saja, latar transparan — avatar, watermark |
14
+ | `png/icon-{16…1024}.png` | ikon persegi sudut membulat — avatar npm/GitHub, app icon |
14
15
  | `png/banner-1200x360.png` | banner README/sosial |
15
16
  | `whatsbibz.ico` | favicon multi-ukuran 16–256 |
16
17
 
17
- Warna: hijau utama `#0a6958`, teks `#2b2e33`, latar putih. Ruang kosong minimal di sekeliling
18
- lockup = tinggi huruf **B**. Jangan dimiringkan, diberi outline, atau diganti fontnya.
19
-
20
- Regenerasi turunan (mark transparan, ikon, ICO, banner) dari master: skrip yang dipakai ada di
21
- riwayat proyek (`scripts/` tidak menyertakannya karena hanya dijalankan sekali saat rebrand).
18
+ Ikon, mark, banner, dan favicon masih turunan dari lockup persegi versi lama.
19
+ Setelah versi final disepakati, turunan tersebut perlu diregenerasi dari `preview.webp`.
Binary file
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Banner ASCII "WhatsBibz." yang dicetak saat client dibuat.
3
+ * Huruf: "Small Slant" (figlet). Warna: filter pelangi (Rainbow 2).
4
+ */
5
+
6
+ export const BANNER_FONT: string;
7
+ export const BANNER_FILTER: string;
8
+
9
+ /** Banner polos tanpa kode warna ANSI (4 baris, tanpa newline tambahan). */
10
+ export const BANNER_TEXT: string;
11
+
12
+ export interface BannerRenderOptions {
13
+ /** true = selalu berwarna, false = polos, 'auto' (default) = ikuti terminal. */
14
+ color?: boolean | 'auto';
15
+ /** Berapa kali spektrum pelangi diulang sepanjang lebar banner (default 1). */
16
+ cycles?: number;
17
+ /** Environment untuk deteksi warna (default process.env). */
18
+ env?: NodeJS.ProcessEnv;
19
+ /** Stream untuk deteksi TTY (default process.stdout). */
20
+ stream?: unknown;
21
+ }
22
+
23
+ export function colorEnabled(opts?: { env?: NodeJS.ProcessEnv; stream?: unknown }): boolean;
24
+
25
+ /** Render banner menjadi string siap cetak (tanpa newline tambahan). */
26
+ export function renderBanner(options?: BannerRenderOptions): string;
27
+
28
+ /** Cetak banner ke terminal. */
29
+ export function printBanner(
30
+ options?: BannerRenderOptions & { write?: (chunk: string) => void },
31
+ ): boolean;
@@ -0,0 +1,120 @@
1
+ // BibzWhats — banner ASCII "WhatsBibz." yang dicetak ke terminal saat client dibuat.
2
+ //
3
+ // • Huruf : "Small Slant" (figlet / smslant) — dirender sekali dan disimpan
4
+ // sebagai string statis, jadi TIDAK butuh dependency figlet saat runtime.
5
+ // • Warna : filter pelangi (gradien hue mengalir dari kiri ke kanan), gaya
6
+ // truecolor (24-bit) dengan fallback palet 256 bila terminal tidak
7
+ // mendukungnya, dan otomatis tanpa warna (plain) bila stdout bukan TTY.
8
+ // • Matikan : NO_COLOR=1, atau opsi client `banner: false`.
9
+
10
+ // Baris asli hasil figlet.textSync('WhatsBibz.', { font: 'Small Slant' }).
11
+ // Perhatikan: sebagian besar glyph saling berimpit karena font-nya miring rapat —
12
+ // itu memang karakteristik "Small Slant".
13
+ const LINES = [
14
+ " _ ____ __ ___ _ __ ",
15
+ " | | /| / / / ___ _/ /____ / _ )(_) / ___ ",
16
+ " | |/ |/ / _ \\/ _ `/ __(_-</ _ / / _ \\/_ /_ ",
17
+ " |__/|__/_//_/\\_,_/\\__/___/____/_/_.__//__(_)",
18
+ ];
19
+
20
+ export const BANNER_FONT = 'Small Slant';
21
+ export const BANNER_FILTER = 'Rainbow 2';
22
+
23
+ const MAX_WIDTH = Math.max(...LINES.map((l) => l.length));
24
+
25
+ /** Banner polos (tanpa ANSI) — 4 baris, tanpa baris kosong di ujung. */
26
+ export const BANNER_TEXT = LINES.map((l) => l.trimEnd()).join('\n');
27
+
28
+ const RESET = '\x1b[0m';
29
+ const TRUE_COLOR_TERMS = new Set(['truecolor', '24bit']);
30
+ const TRUECOLOR_TERM_PROGRAMS = ['iterm.app', 'wezterm', 'vscode', 'hyper', 'tabby', 'ghostty', 'kitty', 'alacritty'];
31
+
32
+ /** Deteksi warna: hormati NO_COLOR / FORCE_COLOR; default hanya saat stdout TTY. */
33
+ export function colorEnabled({ env = process.env, stream = process.stdout } = {}) {
34
+ const nc = env.NO_COLOR;
35
+ if (nc !== undefined && nc !== '' && nc !== '0') return false;
36
+ const fc = env.FORCE_COLOR;
37
+ if (fc !== undefined && fc !== '' && fc !== '0') return true;
38
+ return !!(stream && stream.isTTY) && env.TERM !== 'dumb';
39
+ }
40
+
41
+ function trueColorSupported(env = process.env) {
42
+ const ct = String(env.COLORTERM || '').toLowerCase();
43
+ if (ct && TRUE_COLOR_TERMS.has(ct)) return true;
44
+ const prog = String(env.TERM_PROGRAM || '').toLowerCase();
45
+ return TRUECOLOR_TERM_PROGRAMS.some((p) => prog.includes(p));
46
+ }
47
+
48
+ function hslToRgb(h, s, l) {
49
+ h = ((h % 360) + 360) % 360;
50
+ const c = (1 - Math.abs(2 * l - 1)) * s;
51
+ const hp = h / 60;
52
+ const x = c * (1 - Math.abs((hp % 2) - 1));
53
+ let r = 0, g = 0, b = 0;
54
+ if (hp < 1) [r, g, b] = [c, x, 0];
55
+ else if (hp < 2) [r, g, b] = [x, c, 0];
56
+ else if (hp < 3) [r, g, b] = [0, c, x];
57
+ else if (hp < 4) [r, g, b] = [0, x, c];
58
+ else if (hp < 5) [r, g, b] = [x, 0, c];
59
+ else [r, g, b] = [c, 0, x];
60
+ const m = l - c / 2;
61
+ return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)];
62
+ }
63
+
64
+ // Pendekatan terdekat ke kode palet 256 (cube 6×6×6 atau grayscale).
65
+ const CUBE = [0, 95, 135, 175, 215, 255];
66
+ function nearest256(r, g, b) {
67
+ const map = (v) => CUBE.reduce((best, x) => (Math.abs(x - v) < Math.abs(best - v) ? x : best), CUBE[0]);
68
+ const rr = map(r), gg = map(g), bb = map(b);
69
+ const rgbErr = (rr - r) ** 2 + (gg - g) ** 2 + (bb - b) ** 2;
70
+ const avg = (r + g + b) / 3;
71
+ const grayIdx = Math.min(23, Math.max(0, Math.round((avg - 3) / 10)));
72
+ const grayV = 8 + grayIdx * 10;
73
+ const grayErr = (grayV - r) ** 2 + (grayV - g) ** 2 + (grayV - b) ** 2;
74
+ if (grayErr < rgbErr) return `38;5;${232 + grayIdx}`;
75
+ return `38;5;${16 + 36 * CUBE.indexOf(rr) + 6 * CUBE.indexOf(gg) + CUBE.indexOf(bb)}`;
76
+ }
77
+
78
+ function colorCode(r, g, b, trueColor) {
79
+ return trueColor ? `38;2;${r};${g};${b}` : nearest256(r, g, b);
80
+ }
81
+
82
+ /**
83
+ * Render banner.
84
+ * @param {object} [opts]
85
+ * @param {boolean|'auto'} [opts.color='auto'] true=selalu berwarna, false=polos, 'auto'=ikuti terminal
86
+ * @param {number} [opts.cycles=1] berapa kali spektrum pelangi diulang sepanjang lebar banner
87
+ * @param {object} [opts.env] environment (untuk deteksi warna)
88
+ * @param {object} [opts.stream] stream untuk deteksi TTY (biasanya process.stdout)
89
+ * @returns {string} banner siap dicetak (tanpa newline tambahan)
90
+ */
91
+ export function renderBanner({ color = 'auto', cycles = 1, env = process.env, stream = process.stdout } = {}) {
92
+ const useColor = color === true || (color === 'auto' && colorEnabled({ env, stream }));
93
+ if (!useColor) return BANNER_TEXT;
94
+ const trueColor = trueColorSupported(env);
95
+ return LINES.map((line) => {
96
+ let out = '';
97
+ for (let c = 0; c < line.length; c++) {
98
+ const ch = line[c];
99
+ if (ch === ' ') {
100
+ out += ' ';
101
+ continue;
102
+ }
103
+ const hue = ((c / MAX_WIDTH) * 360 * cycles) % 360;
104
+ const [r, g, b] = hslToRgb(hue, 1, 0.5);
105
+ out += `\x1b[${colorCode(r, g, b, trueColor)}m${ch}${RESET}`;
106
+ }
107
+ return out.trimEnd();
108
+ }).join('\n');
109
+ }
110
+
111
+ /**
112
+ * Cetak banner ke terminal.
113
+ * @param {object} [opts] meneruskan opsi renderBanner + `write`
114
+ * @param {(s:string)=>void} [opts.write] penulis output (default process.stdout.write)
115
+ */
116
+ export function printBanner(opts = {}) {
117
+ const { write = (s) => process.stdout.write(s), ...rest } = opts;
118
+ write(renderBanner(rest) + '\n');
119
+ return true;
120
+ }
@@ -33,6 +33,12 @@ export interface BibzWhatsOptions {
33
33
  logger?: BibzWhatsLogger;
34
34
  /** cetak QR ASCII ke console saat fallback (butuh qrcode-terminal) */
35
35
  printQR?: boolean;
36
+ /**
37
+ * Cetak banner ASCII "WhatsBibz." saat client dibuat.
38
+ * Default (undefined): hanya di terminal interaktif (stdout TTY).
39
+ * true = selalu cetak, false = jangan pernah.
40
+ */
41
+ banner?: boolean;
36
42
  /** opsi tambahan langsung ke makeWASocket (override) */
37
43
  socketConfig?: Partial<SocketConfig>;
38
44
  maxReconnectAttempts?: number;
@@ -55,7 +61,7 @@ export interface BibzWhatsOptions {
55
61
  /** default true: 'ready' dipancarkan untuk setiap socket baru (pertama & tiap reconnect) */
56
62
  readyOnEveryConnect?: boolean;
57
63
  }
58
- export declare const BIBZWHATS_DEFAULTS: Readonly<Required<Omit<BibzWhatsOptions, 'phone' | 'pairingCode' | 'logger' | 'printQR' | 'socketConfig'>>>;
64
+ export declare const BIBZWHATS_DEFAULTS: Readonly<Required<Omit<BibzWhatsOptions, 'phone' | 'pairingCode' | 'logger' | 'printQR' | 'socketConfig' | 'banner'>>>;
59
65
  export declare function wipeAuthDir(dir: string): boolean;
60
66
  export declare function makeSocketNetworkOptions(opts?: { forceIPv4?: boolean }): Partial<SocketConfig>;
61
67
  export declare function sessionWipeReason(status: number | undefined, message?: string): string | null;
@@ -24,6 +24,7 @@ import { Browsers } from '../Utils/browser-utils.js';
24
24
  import { lintIdentity, derivePairingDisplay } from '../Utils/platform-identity.js';
25
25
  import { resolveDeviceIdentity, createIdentityRotator, isIdentityRejection, describeIdentity, clearIdentityState, loadIdentityState, saveIdentityState } from './device-identity.js';
26
26
  import { createPairingController } from './pairing.js';
27
+ import { printBanner } from './banner.js';
27
28
 
28
29
  export const BIBZWHATS_DEFAULTS = Object.freeze({
29
30
  authDir: 'bibzwhats-session',
@@ -106,6 +107,9 @@ function mergeLogger(logger) {
106
107
  * @property {[string,string,string]} [browser] alias lama `identity` (tuple eksplisit)
107
108
  * @property {object} [logger] {info,warn,error,ok,debug}
108
109
  * @property {boolean} [printQR] cetak QR ASCII ke console saat fallback (butuh qrcode-terminal)
110
+ * @property {boolean} [banner] cetak banner ASCII 'WhatsBibz.' saat client dibuat.
111
+ * default: hanya di terminal interaktif (stdout TTY);
112
+ * true = selalu, false = jangan pernah.
109
113
  * @property {object} [socketConfig] opsi tambahan langsung ke makeWASocket (override)
110
114
  * @property {string} [companionPlatformDisplay] override `companion_platform_display` (WA memvalidasi dgn allow-list; default diturunkan otomatis, mis. "Chrome (Mac OS)" / "Chrome (Linux)")
111
115
  * @property {boolean} [readyOnEveryConnect] default true — 'ready' tiap socket baru; false = hanya sekali
@@ -127,6 +131,14 @@ export async function createBibzWhats(options = {}) {
127
131
  const emitter = new EventEmitter();
128
132
  const groupMetadataCache = new Map();
129
133
 
134
+ // Banner ASCII 'WhatsBibz.' (Small Slant, pelangi) — hanya terminal interaktif secara
135
+ // bawaan; `banner: true` memaksa cetak (mis. untuk log/daemon), `banner: false` mematikan.
136
+ const wantBanner =
137
+ opts.banner === true || (opts.banner !== false && !!process.stdout.isTTY);
138
+ if (wantBanner) {
139
+ try { printBanner(); } catch {}
140
+ }
141
+
130
142
  // ── Identitas perangkat tertaut: kustom (opsi/env) atau otomatis (paling stabil) ──
131
143
  const resolved = resolveDeviceIdentity({ identity: opts.identity === 'auto' ? undefined : opts.identity, browser: opts.browser, authDir: opts.authDir });
132
144
  for (const note of resolved.notes) (note.level === 'warn' ? log.warn : log.info)(`BibzWhats: ${note.message}`);
@@ -4,4 +4,5 @@ export * from './device-identity.js';
4
4
  export * from './send.js';
5
5
  export * from './extract.js';
6
6
  export * from './jid.js';
7
+ export * from './banner.js';
7
8
  export { BIBZWHATS_VERSION, BIBZWHATS_NAME, BIBZWHATS_PACKAGE, BIBZWHATS_UPSTREAM, BIBZWHATS_WA_WEB_VERSION } from './version.js';
@@ -5,4 +5,5 @@ export * from './device-identity.js';
5
5
  export * from './send.js';
6
6
  export * from './extract.js';
7
7
  export * from './jid.js';
8
+ export * from './banner.js';
8
9
  export { BIBZWHATS_VERSION, BIBZWHATS_NAME, BIBZWHATS_PACKAGE, BIBZWHATS_UPSTREAM, BIBZWHATS_WA_WEB_VERSION } from './version.js';
@@ -1,7 +1,7 @@
1
1
  export const BIBZWHATS_NAME = 'WhatsBibz';
2
2
  /** nama paket di npm */
3
3
  export const BIBZWHATS_PACKAGE = '@xbibzlibrary/whatsbibz';
4
- export const BIBZWHATS_VERSION = '1.3.1';
4
+ export const BIBZWHATS_VERSION = '1.4.0';
5
5
  export const BIBZWHATS_UPSTREAM = 'ourin-baileys@9.0.21 (fork WhiskeySockets/Baileys v7) + patch upstream s/d rc14/master 2026-08 & PR #2769/#2776/#2778/#2789; identitas platform diukur ke server 2026-09-03';
6
6
  /** versi WA Web bawaan (fallback) — diperbarui 2026-09-03 dari web.whatsapp.com */
7
- export const BIBZWHATS_WA_WEB_VERSION = [2, 3000, 1046721733];
7
+ export const BIBZWHATS_WA_WEB_VERSION = [2, 3000, 1046874154];
@@ -2,7 +2,7 @@ import { proto } from "../../WAProto/index.js";
2
2
  import { makeLibSignalRepository } from "../Signal/libsignal.js";
3
3
  import { Browsers } from "../Utils/browser-utils.js";
4
4
  import logger from "../Utils/logger.js";
5
- const version = [2, 3000, 1046721733];
5
+ const version = [2, 3000, 1046874154];
6
6
  export const UNAUTHORIZED_CODES = [401, 403, 419];
7
7
  export const DEFAULT_ORIGIN = "https://web.whatsapp.com";
8
8
  export const CALL_VIDEO_PREFIX = "https://call.whatsapp.com/video/";
@@ -813,18 +813,15 @@ class Button extends BaseBuilder {
813
813
  }
814
814
 
815
815
  async build(jid, { ...options } = {}) {
816
- if (this._cardBuilders && this._cardBuilders.length > 0) {
817
- for (const builder of this._cardBuilders) {
818
- this.addCard(await builder._card.toCard());
819
- }
820
- this._cardBuilders = [];
821
- }
816
+ // Konten interactive message = hasil toCard() (body/footer/header + nativeFlowMessage).
817
+ // Sebelumnya memakai variabel `message` yang tidak pernah didefinisikan → ReferenceError.
818
+ const payload = await this.toCard();
822
819
  return generateWAMessageFromContent(
823
820
  jid,
824
821
  {
825
822
  ...this._extraPayload,
826
823
  interactiveMessage: {
827
- ...message,
824
+ ...payload,
828
825
  contextInfo: this._contextInfo,
829
826
  },
830
827
  },
@@ -833,6 +830,7 @@ class Button extends BaseBuilder {
833
830
  }
834
831
 
835
832
  async send(jid, { ...options } = {}) {
833
+ if (this._buttons.length < 1) throw new Error('Button requires at least one button');
836
834
  const msg = await this.build(jid, options);
837
835
 
838
836
  await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
@@ -997,7 +995,17 @@ class Carousel extends BaseBuilder {
997
995
  return this;
998
996
  }
999
997
 
1000
- build(jid, { ...options } = {}) {
998
+ async build(jid, { ...options } = {}) {
999
+ // Konsumsi builder terdaftar lewat .card(cb). Sebelumnya _cardBuilders tidak pernah
1000
+ // dipakai di sini → carousel terkirim dengan 0 kartu (diam-diam rusak).
1001
+ if (this._cardBuilders && this._cardBuilders.length > 0) {
1002
+ const built = [];
1003
+ for (const builder of this._cardBuilders) {
1004
+ built.push(await builder._card.toCard());
1005
+ }
1006
+ this._cardBuilders = [];
1007
+ this.addCard(built);
1008
+ }
1001
1009
  return generateWAMessageFromContent(
1002
1010
  jid,
1003
1011
  {
@@ -1019,6 +1027,15 @@ class Carousel extends BaseBuilder {
1019
1027
  }
1020
1028
 
1021
1029
  async send(jid, { ...options } = {}) {
1030
+ if (this._cardBuilders && this._cardBuilders.length > 0) {
1031
+ const built = [];
1032
+ for (const builder of this._cardBuilders) {
1033
+ built.push(await builder._card.toCard());
1034
+ }
1035
+ this._cardBuilders = [];
1036
+ this.addCard(built);
1037
+ }
1038
+ if (this._cards.length < 1) throw new Error('Carousel requires at least one card');
1022
1039
  const msg = await this.build(jid, options);
1023
1040
 
1024
1041
  await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
@@ -28,9 +28,9 @@ export const Browsers = {
28
28
  linux: browser => ['Linux', browser, '6.12.44'],
29
29
  baileys: browser => ['Baileys', browser, '6.5.0'],
30
30
  /** identitas companion BibzWhats (tampil di daftar perangkat tertaut) */
31
- whatsbibz: browser => ['WhatsBibz', browser, '1.3.1'],
31
+ whatsbibz: browser => ['WhatsBibz', browser, '1.4.0'],
32
32
  /** alias lama */
33
- bibzwhats: browser => ['WhatsBibz', browser, '1.3.1'],
33
+ bibzwhats: browser => ['WhatsBibz', browser, '1.4.0'],
34
34
  windows: browser => ['Windows', browser, '10.0.22631'],
35
35
  /** eksperimental (upstream #2201): companion Android — bisa menerima view-once */
36
36
  android: browser => [browser, 'Android', ''],
@@ -1,7 +1,7 @@
1
1
  import { Boom } from '@hapi/boom';
2
2
  import { createHash, randomBytes } from 'crypto';
3
3
  import { proto } from '../../WAProto/index.js';
4
- const bibzWhatsVersion = [2, 3000, 1046721733];
4
+ const bibzWhatsVersion = [2, 3000, 1046874154];
5
5
  import { DisconnectReason } from '../Types/index.js';
6
6
  import { getAllBinaryNodeChildren, jidDecode } from '../WABinary/index.js';
7
7
  import { sha256 } from './crypto.js';
@@ -544,6 +544,16 @@ export const captureUnifiedResponse = (msg) => {
544
544
  };
545
545
  };
546
546
  export const generateUnifiedResponseContent = (quoted, captured) => {
547
+ if (
548
+ !captured ||
549
+ !Array.isArray(captured.submessages) ||
550
+ !captured.unifiedResponse?.data
551
+ ) {
552
+ throw new TypeError(
553
+ 'captured wajib berupa hasil captureUnifiedResponse(msg) yang berisi ' +
554
+ 'unifiedResponse.data — contoh: sock.sendUnifiedResponse(jid, quoted, captureUnifiedResponse(m.message))',
555
+ );
556
+ }
547
557
  const ctxInfo = buildRichContextInfo(quoted);
548
558
  return {
549
559
  message: buildBotForwardedMessage(
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xbibzlibrary/whatsbibz",
3
- "version": "1.3.1",
4
- "description": "WhatsBibz — library WhatsApp Web multi-device (fork Baileys v7 / ourin-baileys) untuk ekosistem Xbibz: pairing code custom, identitas perangkat kustom/otomatis, auto-reconnect, self-healing session, handler companion_reg_refresh bawaan, interactive message, album, newsletter, VoIP.",
3
+ "version": "1.4.0",
4
+ "description": "WhatsBibz — WhatsApp Web multi-device library for Node.js (maintained Baileys fork): high-level client, custom pairing codes, self-healing sessions, configurable or automatic linked-device identity, complete TypeScript declarations.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -20,6 +20,7 @@
20
20
  "LICENSE",
21
21
  "LICENSE.upstream",
22
22
  "README.md",
23
+ "README.id.md",
23
24
  "CHANGELOG.md",
24
25
  "assets/logo/preview.png",
25
26
  "assets/logo/whatsbibz.ico",
@@ -27,7 +28,8 @@
27
28
  "assets/logo/png/mark-512.png",
28
29
  "assets/logo/png/banner-1200x360.png",
29
30
  "assets/logo/README.md",
30
- "VERIFIKASI-IDENTITAS-2026-09-03.md"
31
+ "VERIFIKASI-IDENTITAS-2026-09-03.md",
32
+ "SECURITY.md"
31
33
  ],
32
34
  "scripts": {
33
35
  "test": "node --test test/*.test.js",
@@ -50,9 +52,21 @@
50
52
  "bot",
51
53
  "automation"
52
54
  ],
53
- "author": "Xbibz Developer",
55
+ "author": {
56
+ "name": "Xbibz Developer",
57
+ "email": "revandoppratama@gmail.com",
58
+ "url": "https://github.com/XbibzOfficial777"
59
+ },
54
60
  "license": "MIT",
55
- "homepage": "https://www.npmjs.com/package/@xbibzlibrary/whatsbibz",
61
+ "homepage": "https://github.com/XbibzOfficial777/whatsbibz#readme",
62
+ "repository": {
63
+ "type": "git",
64
+ "url": "git+https://github.com/XbibzOfficial777/whatsbibz.git"
65
+ },
66
+ "bugs": {
67
+ "url": "https://github.com/XbibzOfficial777/whatsbibz/issues",
68
+ "email": "revandoppratama@gmail.com"
69
+ },
56
70
  "engines": {
57
71
  "node": ">=20.0.0"
58
72
  },
@@ -105,7 +119,7 @@
105
119
  }
106
120
  },
107
121
  "devDependencies": {
108
- "typescript": "^5.9.2",
122
+ "typescript": "^7.0.2",
109
123
  "@types/node": "^22.18.0"
110
124
  }
111
125
  }