npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

foxxy-baileys

v0.0.1

Published

Baileys v7 modifikasi dengan dukungan pesan interaktif, album, dan newsletter

Readme

Baileys Modifikasi — Pesan Interaktif, Respons Kaya AI, Album & Lainnya

npm version npm downloads License Node ESM


Sebuah build modifikasi dari WhiskeySockets/Baileys dengan dukungan bawaan untuk pesan interaktif, pesan album, respons kaya terpadu, helper newsletter, mention status, serta utilitas bisnis/komunitas tambahan.

Repositori ini adalah repo distribusi/build untuk foxxy-baileys. Repo ini menyediakan file runtime hasil kompilasi di lib/ dan artefak protobuf di WAProto/, dan ditujukan untuk digunakan langsung dari npm atau sebagai dependensi vendor di dalam ekosistem Foxxy-MD.


🆕 Changelog / Pembaruan (v0.0.1)

1. Perbaikan Error View Once (Anti-Crash)

  • Meta (WhatsApp) Web API tidak lagi menerima konten media untuk pesan View Once, yang sebelumnya menyebabkan socket crash. Kami telah menambahkan parsing yang lebih tangguh (viewOnceMessageV3 & ptvMessage) untuk menangani stub kosong ini dengan baik tanpa membuat bot Anda crash.

2. Perbaikan Retry Dekripsi (Chat Pribadi)

  • Memperbaiki masalah di messages-recv.js di mana error "Bad MAC" / dekripsi dapat menutup koneksi. Dikombinasikan dengan hook getMessage yang tepat pada setup koneksi utama Anda, bot kini secara otomatis mencoba ulang dekripsi yang gagal.
  • Spoofing parameter browser ditingkatkan ke MacOS untuk mencegah Error 405 (Method Not Allowed) saat proses pairing.

3. Implementasi AI Rich (ORich)

  • Menambahkan class ORich (ekstensi dari AIRich pada message_builder.js) untuk membuat tampilan respons AI yang menarik dengan mudah.

  • Contoh Penggunaan:

    import { ORich } from 'foxxy-baileys';
    
    const ourin = new ORich(sock)
      .addText('Halo dari ORich AI!')
      .addSuggest(['Ceritakan lebih lanjut', 'Berikutnya']);
      
    await ourin.send(jid);

Daftar Isi


✨ Fitur

| Fitur | Deskripsi | Status | | ------------------------------ | ---------------------------------------------------------------------------------------- | ------ | | Pesan Interaktif | Tombol native flow, menu list/select, wrapper tombol, dukungan carousel via Dugong | ✅ | | Pesan Album | Relay album multi-gambar/video dengan metadata jumlah dan pengiriman terkelompok | ✅ | | Helper Respons Kaya | sendTable, sendList, sendCodeBlock, sendRichMessage, sendUnifiedResponse | ✅ | | Respons Terpadu V2 | sendTableV2, sendCodeBlockV2, sendLinkV2 dengan bagian terpadu bergaya Meta-AI | ✅ | | Pesan Link | Link inline kaya dengan sitasi, bukti verifikasi, dan konteks forward bot | ✅ | | Hook Rendering Latex | API helper sendLatex, sendLatexImage, sendLatexInlineImage | ✅ | | Pesan Pembayaran | Pesan permintaan pembayaran dengan dukungan catatan/stiker | ✅ | | Produk / Katalog | Pesan produk bisnis, fetch/create/update/delete katalog, helper foto sampul | ✅ | | Event / Hasil Polling | Pembuat pesan event dan snapshot hasil polling | ✅ | | Ekstra Newsletter | Resolve URL, fetch metadata, create/update, follow massal, utilitas admin, live update | ✅ | | Komunitas & Grup | CRUD komunitas, grup tertaut, alur undangan, persetujuan gabung, label | ✅ | | Status Mention | Helper sendStatusMention() untuk mention user/grup dalam alur status | ✅ | | Penanganan LID & Sesi | Pemetaan LID↔PN, migrasi sesi, helper retry/pembuatan ulang sesi | ✅ | | Siap Build Output | Runtime terpublikasi di lib/ dan artefak protobuf di WAProto/ | ✅ | | Deklarasi TypeScript | File .d.ts disertakan untuk API dan metode socket yang diekspor | ✅ |


✅ Persyaratan

  • Node.js >= 20.0.0
  • Proyek ESM ("type": "module" di package.json Anda)
  • Implementasi penyimpanan auth yang persisten untuk penggunaan produksi
  • Helper opsional tergantung kebutuhan Anda:
    • pino untuk logging
    • qrcode-terminal jika Anda ingin merender kode QR di terminal sendiri
    • sharp, jimp, audio-decode, link-preview-js untuk utilitas media/kaya opsional

[!IMPORTANT] foxxy-baileys hanya mendukung ESM. Proyek CommonJS memerlukan migrasi atau wrapper dynamic import.


📁 Isi Repositori Ini

Paket ini bukan workspace sumber TypeScript. Paket ini berisi file distribusi hasil kompilasi yang sebenarnya Anda publikasikan/gunakan.

| Path | Kegunaan | | ----------------------- | ------------------------------------------------------------- | | lib/ | Runtime utama hasil kompilasi, tipe, lapisan socket, utilitas | | WAProto/ | Runtime dan typing protobuf hasil generate | | package.json | Metadata paket terpublikasi, dependensi, skrip build | | tsconfig.json | Konfigurasi TypeScript untuk penulisan/pipeline build | | tsconfig.build.json | Konfigurasi emit TS khusus build yang menargetkan lib/ | | proto-extract/ | Aset ekstraksi/build terkait protobuf |

Jika Anda mendokumentasikan atau mengintegrasikan proyek ini, perlakukan lib/index.js dan lib/index.d.ts sebagai permukaan publik utama.


📦 Instalasi

Dari NPM

npm install foxxy-baileys

Paket pendamping yang direkomendasikan untuk contoh di README ini:

npm install pino qrcode-terminal

Menggunakan Alias (Direkomendasikan untuk Bot Foxxy-MD)

Tambahkan ke package.json:

{
  "dependencies": {
    "foxxy": "npm:foxxy-baileys@latest"
  }
}

Lalu jalankan:

npm install

[!TIP] Menggunakan alias foxxy memungkinkan Anda melakukan import foxxy from 'foxxy' tanpa mengubah kode yang sudah ada.

[!NOTE] Peer dependency seperti sharp, jimp, audio-decode, dan link-preview-js bersifat opsional. Instal hanya yang dibutuhkan fitur bot Anda.


🛠️ Mulai Cepat

1. Setup Proyek

mkdir bot-saya && cd bot-saya
npm init -y

Pastikan package.json memiliki "type": "module":

{
  "name": "bot-saya",
  "type": "module",
  "dependencies": {
    "foxxy": "npm:foxxy-baileys@latest"
  }
}

[!IMPORTANT] Wajib: "type": "module" — foxxy-baileys hanya mendukung ESM. Tanpa ini, import akan gagal.

2. Instal Dependensi

npm install foxxy-baileys pino qrcode-terminal

3. Membuat index.js

import makeWASocket, {
  useMultiFileAuthState,
  DisconnectReason,
  Browsers,
} from "foxxy-baileys";
import pino from "pino";
import qrcode from "qrcode-terminal";

const logger = pino({ level: "silent" });

async function startBot() {
  const { state, saveCreds } = await useMultiFileAuthState("./session");

  const sock = makeWASocket({
    auth: state,
    logger,
    browser: Browsers.ubuntu("Chrome"),
    syncFullHistory: false,
  });

  sock.ev.on("creds.update", saveCreds);

  sock.ev.on("connection.update", ({ connection, lastDisconnect, qr }) => {
    if (qr) {
      qrcode.generate(qr, { small: true });
    }

    if (connection === "close") {
      const shouldReconnect =
        lastDisconnect?.error?.output?.statusCode !==
        DisconnectReason.loggedOut;
      if (shouldReconnect) startBot();
    }
    if (connection === "open") console.log("Terhubung!");
  });

  sock.ev.on("messages.upsert", async ({ messages }) => {
    const msg = messages[0];
    if (!msg?.message || msg.key.fromMe) return;

    const text =
      msg.message.conversation || msg.message.extendedTextMessage?.text || "";

    if (text === ".ping") {
      await sock.sendMessage(msg.key.remoteJid, { text: "Pong!" });
    }
  });
}

startBot();

4. Jalankan

node index.js

Pindai kode QR, tunggu hingga socket mencapai connection: "open", lalu kirim .ping untuk menguji.

5. Contoh Kode Pairing

Jika Anda lebih memilih kode pairing daripada QR:

const sock = makeWASocket({
  auth: state,
  logger,
  browser: Browsers.windows("Chrome"),
});

sock.ev.on("connection.update", async ({ connection }) => {
  if (connection === "connecting") {
    const code = await sock.requestPairingCode("6281234567890");
    console.log("Kode pairing:", code);
  }
});

Anda juga dapat menyediakan kode pairing kustom Anda sendiri:

const code = await sock.requestPairingCode("6281234567890", "A1B2C3D4");
console.log("Kode pairing kustom:", code);

Kode pairing kustom harus tepat 8 karakter.

[!WARNING] printQRInTerminal masih ada pada permukaan tipe untuk kompatibilitas, namun sudah usang (deprecated) pada build saat ini. Sebaiknya tangani sendiri nilai qr dari connection.update.


🏗️ Arsitektur

Rantai Lapisan Socket

Setiap lapisan socket memperluas lapisan sebelumnya melalui komposisi, menambahkan fungsionalitas dari bawah ke atas:

makeSocket          → WebSocket + protokol Noise + manajemen pre-key
  makeChatsSocket   → Sinkronisasi app state + modifikasi chat + profil
    makeGroupsSocket → CRUD grup + manajemen partisipan
      makeMessagesSendSocket → Pengiriman pesan + pesan kaya + relay
        makeMessagesRecvSocket → Penerimaan pesan + dekripsi + notifikasi
          makeBusinessSocket   → Katalog produk + profil bisnis
            makeCommunitiesSocket → CRUD komunitas + sub-grup
              makeNewsletterSocket → Follow/unfollow/metadata newsletter
                makeWASocket      ← EKSPOR LEVEL TERATAS

Modul Utama

| Modul | Path | Deskripsi | | ------------ | --------------- | -------------------------------------------------------------------- | | Socket | lib/Socket/ | Koneksi, pesan, grup, newsletter, bisnis, komunitas | | Signal | lib/Signal/ | Protokol Signal: enkripsi 1:1, SenderKey grup, pemetaan LID | | WABinary | lib/WABinary/ | Encoding/decoding binary node, utilitas JID | | Utils | lib/Utils/ | Kripto, auth state, penanganan noise, pesan kaya, media | | WAProto | WAProto/ | Encode/decode protobuf hasil kompilasi | | WAUSync | lib/WAUSync/ | Protokol sinkronisasi user (kontak, perangkat, LID) | | WAM | lib/WAM/ | Encoding binary analitik WhatsApp | | Types | lib/Types/ | Definisi tipe TypeScript lengkap |

Struktur Repo Build

Repositori ini tidak menyediakan direktori src/ pada tree paket yang di-commit.

Artinya:

  • Dokumentasi sebaiknya merujuk pada lib/ sebagai implementasi publik
  • Eksplorasi API paling baik dilakukan melalui:
    • lib/index.js
    • lib/index.d.ts
    • lib/Socket/*.d.ts
    • lib/Utils/*.d.ts
  • Pengguna sebaiknya memperlakukan repo ini sebagai artefak runtime siap-instal, bukan tree sumber penulisan

Alur Koneksi

  1. Koneksi WebSocket → handshake Noise XX (Curve25519 + AES-256-GCM)
  2. Autentikasi kode QR atau kode Pairing
  3. CB:success → unggah pre-key → kirim IQ pasif → emit connection: 'open'
  4. Simpan pemetaan LID↔PN milik sendiri, migrasi sesi sendiri
  5. Buffer event → proses notifikasi offline → flush → receivedPendingNotifications: true

📡 Referensi API Socket

Koneksi & Autentikasi

const sock = makeWASocket({
  auth: state, // AuthenticationState dari useMultiFileAuthState
  logger, // instance logger pino
  browser: Browsers.ubuntu("Chrome"), // Identitas browser
  version: [2, 3000, 1035194821], // Versi WA
  connectTimeoutMs: 20_000, // Timeout koneksi
  defaultQueryTimeoutMs: 60_000, // Timeout query
  retryRequestDelayMs: 250, // Delay retry
  maxMsgRetryCount: 5, // Jumlah maksimal retry pesan
  enableRecentMessageCache: true, // Aktifkan message retry manager
  enableAutoSessionRecreation: true,
  syncFullHistory: false, // Sinkronisasi riwayat chat penuh
  shouldIgnoreJid: (jid) => false, // Filter JID tertentu
  qrTimeout: 60_000,
  generateHighQualityLinkPreview: false,
});

Autentikasi Kode Pairing:

const sock = makeWASocket({
  auth: state,
  logger,
  browser: Browsers.windows("Chrome"),
});

sock.ev.on("connection.update", async ({ connection, qr, isNewLogin }) => {
  if (qr) {
    // Kode QR tersedia (fallback)
  }
});

// Minta kode pairing
const code = await sock.requestPairingCode("6281234567890");
console.log("Kode pairing:", code); // contoh "A1B2-C3D4"

Authentication State:

import { useMultiFileAuthState } from "foxxy-baileys";

const { state, saveCreds } = await useMultiFileAuthState("./session");
// state.creds → kredensial (me, platform, noise keys, dll.)
// state.keys → SignalKeyStore (pre-key, sesi, identity key, dll.)
// saveCreds() → simpan kredensial ke disk

Pola Custom Data Store / Memory Store:

import {
  BufferJSON,
  initAuthCreds,
  makeCacheableSignalKeyStore,
} from "foxxy-baileys";

const credsStore = new Map();
const keyStoreData = new Map();

const creds = credsStore.get("creds") || initAuthCreds();

const keys = makeCacheableSignalKeyStore({
  get: async (type, ids) => {
    const data = {};
    for (const id of ids) {
      data[id] = keyStoreData.get(`${type}:${id}`);
    }
    return data;
  },
  set: async (data) => {
    for (const category in data) {
      for (const id in data[category]) {
        const value = data[category][id];
        const key = `${category}:${id}`;
        if (value == null) keyStoreData.delete(key);
        else keyStoreData.set(key, value);
      }
    }
  },
});

const state = { creds, keys };

const saveCreds = async () => {
  credsStore.set(
    "creds",
    JSON.parse(
      JSON.stringify(state.creds, BufferJSON.replacer),
      BufferJSON.reviver,
    ),
  );
};

Paket ini tidak menyediakan helper makeInMemoryStore() bawaan.

Gunakan pola berikut sebagai gantinya:

  • useMultiFileAuthState() untuk penggunaan bot/lokal
  • initAuthCreds() + SignalKeyStore kustom untuk persistensi DB/Redis/in-memory
  • makeCacheableSignalKeyStore() jika Anda ingin akses key berulang yang lebih cepat dengan caching

[!WARNING] useMultiFileAuthState() praktis untuk bot dan pengujian lokal, tetapi paket ini sendiri memperingatkan agar tidak digunakan sebagai lapisan persistensi produksi jangka panjang. Untuk produksi, buat auth store berbasis SQL/NoSQL Anda sendiri.

Helper pendamping yang berguna:

import {
  Browsers,
  DisconnectReason,
  fetchLatestBaileysVersion,
  makeCacheableSignalKeyStore,
} from "foxxy-baileys";

const { version, isLatest } = await fetchLatestBaileysVersion();
console.log(version, isLatest);

Pengiriman Pesan

// Teks
await sock.sendMessage(jid, { text: "Halo!" });

// Teks dengan mention
await sock.sendMessage(jid, {
  text: "Halo @628xxx!",
  mentions: ["[email protected]"],
});

// Gambar
await sock.sendMessage(jid, {
  image: { url: "./foto.jpg" },
  caption: "Sebuah foto",
});

// Video
await sock.sendMessage(jid, {
  video: { url: "./video.mp4" },
  caption: "Sebuah video",
  gifPlayback: false,
});

// Audio
await sock.sendMessage(jid, {
  audio: { url: "./audio.ogg" },
  mimetype: "audio/ogg; codecs=opus",
  ptt: true, // pesan suara
});

// Stiker
await sock.sendMessage(jid, {
  sticker: { url: "./stiker.webp" },
});

// Paket stiker
await sock.sendMessage(
  jid,
  makeStickerPack({
    name: "Foxxy Starter Pack",
    publisher: "Foxxy",
    description: "Paket stiker awal",
    stickers: [
      { url: "./stickers/1.webp", emojis: ["🔥"] },
      { url: "./stickers/2.webp", emojis: ["😎"] },
    ],
    cover: { url: "./stickers/cover.webp" },
  }),
);

// Dokumen
await sock.sendMessage(jid, {
  document: { url: "./file.pdf" },
  fileName: "dokumen.pdf",
  mimetype: "application/pdf",
});

// Reaksi
await sock.sendMessage(jid, {
  react: { key: msg.key, text: "👍" },
});

// Lokasi
await sock.sendMessage(jid, {
  location: {
    degreesLatitude: -6.2,
    degreesLongitude: 106.8,
    name: "Jakarta",
  },
});

// Kontak
await sock.sendMessage(jid, {
  contacts: {
    displayName: "Kontak",
    contacts: [
      { vcard: "BEGIN:VCARD\nVERSION:3.0\nFN:John\nTEL:+628xxx\nEND:VCARD" },
    ],
  },
});

// Polling
await sock.sendMessage(jid, {
  poll: {
    name: "Ayo Voting!",
    values: ["Opsi A", "Opsi B", "Opsi C"],
    selectableCount: 1,
  },
});

// Forward pesan
await sock.sendMessage(jid, {
  forward: msg,
  forwardingScore: 1,
  isForwarded: true,
});

// Hapus pesan
await sock.sendMessage(jid, { delete: msg.key });

// Edit pesan
await sock.sendMessage(jid, {
  text: "Teks yang sudah diedit",
  edit: msg.key,
});

Pesan Interaktif

Tombol Native Flow:

await sock.sendMessage(jid, {
  interactiveMessage: {
    title: "Selamat Datang!",
    footer: "Didukung oleh Foxxy",
    buttons: [
      {
        name: "quick_reply",
        buttonParamsJson: JSON.stringify({
          display_text: "Menu",
          id: "menu",
        }),
      },
      {
        name: "cta_url",
        buttonParamsJson: JSON.stringify({
          display_text: "Website",
          url: "https://example.com",
        }),
      },
      {
        name: "cta_copy",
        buttonParamsJson: JSON.stringify({
          display_text: "Salin Kode",
          copy_code: "FOXXY2024",
        }),
      },
    ],
    header: "Pilih salah satu opsi",
    image: { url: "https://example.com/banner.jpg" },
  },
});

Menu List (single_select):

await sock.sendMessage(jid, {
  interactiveMessage: {
    title: "Pilih Kategori",
    footer: "Didukung oleh Foxxy",
    buttons: [
      {
        name: "single_select",
        buttonParamsJson: JSON.stringify({
          title: "Menu",
          sections: [
            {
              title: "Game",
              rows: [
                { title: "Kuis", id: ".quiz" },
                { title: "Tebak Gambar", id: ".tebakgambar" },
              ],
            },
            {
              title: "Tools",
              rows: [
                { title: "Stiker", id: ".sticker" },
                { title: "TTS", id: ".tts" },
              ],
            },
          ],
        }),
      },
    ],
    header: "Menu Bot",
  },
});

Pesan Album

await sock.sendMessage(jid, {
  albumMessage: [
    { image: { url: "./foto1.jpg" }, caption: "Pertama" },
    { image: { url: "./foto2.jpg" }, caption: "Kedua" },
    { video: { url: "./klip.mp4" }, caption: "Video" },
  ],
});

[!NOTE] Album secara otomatis mengatur expectedImageCount dan expectedVideoCount berdasarkan isi array.


Pesan Respons Kaya AI

Kirim pesan bergaya Meta AI — tabel, code block, dan teks kaya. Semuanya dirender melalui botForwardedMessage > richResponseMessage.

Tabel (dengan judul):

await sock.sendTable(
  jid,
  "Java vs JavaScript",
  ["Fitur", "Java", "JavaScript"],
  [
    ["Tipe", "Compiled", "Interpreted"],
    ["Typing", "Statis", "Dinamis"],
    ["Kegunaan Utama", "Enterprise", "Web, Full-stack"],
  ],
  quoted,
  {
    headerText: "Perbandingan:",
    footer: "Semoga membantu!",
  },
);

List (tanpa judul):

await sock.sendList(
  jid,
  "Info Bot",
  [
    ["Nama", "Foxxy AI"],
    ["Versi", "0.0.1"],
    ["Developer", "Wanz"],
  ],
  quoted,
  { footer: "© Foxxy AI" },
);

Code Block V1 (syntax highlighting dasar):

await sock.sendCodeBlock(
  jid,
  `const greeting = "Hello World"
function sayHello(name) {
    return greeting + " " + name
}
sayHello("Foxxy")`,
  quoted,
  {
    language: "javascript",
    title: "Contoh Kode",
    footer: "Didukung oleh Foxxy",
  },
);

Bahasa V1 yang didukung: javascript, typescript, python

Tabel V2 (Respons Terpadu):

Tabel V2 menggunakan format respons terpadu dengan typename GenATableUXPrimitive dan data ter-encode base64, mengikuti protokol respons kaya Meta AI.

Fitur tambahan dibanding V1:

  • Input tabel berbasis string dengan delimiter fleksibel (| atau , untuk kolom, ;; untuk baris)
  • Bagian respons terpadu dengan typename GenATableUXPrimitive / GenAIMarkdownTextUXPrimitive
  • Output ganda: rows (untuk submessage) + unified_rows (untuk bagian/section)
  • contextInfo yang ditingkatkan dengan botMessageSharingInfo
await sock.sendTableV2(
  jid,
  [
    "Java vs JavaScript", // judul
    "Fitur | Java | JavaScript", // header (dipisah pipe)
    "Tipe | Compiled | Interpreted;;Typing | Statis | Dinamis;;Kegunaan Utama | Enterprise | Web, Full-stack", // baris (dipisah ;;, kolom dipisah | atau ,)
  ],
  quoted,
  {
    headerText: "Perbandingan:",
    text: "Berikut adalah tabel perbandingannya:",
    footer: "Semoga membantu!",
  },
);

Format input:

  • table[0] — string judul
  • table[1] — baris header (kolom dipisahkan | atau ,)
  • table[2+] — baris data (baris dipisahkan ;;, kolom dipisahkan | atau ,)

Opsi V2:

| Opsi | Tipe | Default | Deskripsi | | ------------ | -------- | ------- | -------------------------------------------------- | | title | string | — | Judul (dipakai jika headerText tidak diatur) | | headerText | string | — | Teks yang tampil sebelum tabel | | text | string | — | Bagian teks markdown (GenAIMarkdownTextUXPrimitive) | | footer | string | — | Teks yang tampil setelah tabel |


Code Block V2 (Respons Terpadu)

Code block V2 menggunakan format respons terpadu dengan struktur sections/view_model/primitive dan data ter-encode base64, mengikuti protokol respons kaya Meta AI secara persis.

Fitur tambahan dibanding V1:

  • 6 keluarga bahasa dengan deteksi keyword
  • Dukungan komentar blok /* */
  • Dukungan komentar # untuk python/bash/lua
  • Literal angka hex/biner/oktal
  • Output token ganda: codeBlock numerik + unified_codeBlock bertipe string
  • Bagian respons terpadu dengan typename GenAICodeUXPrimitive / GenAIMarkdownTextUXPrimitive
  • contextInfo yang ditingkatkan dengan botMessageSharingInfo
await sock.sendCodeBlockV2(
  jid,
  `package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}`,
  quoted,
  {
    language: "go",
    title: "Contoh Go",
    text: "Berikut adalah cuplikan kode Go:",
    footer: "Didukung oleh Foxxy",
  },
);

Bahasa V2 yang didukung:

| Kunci Bahasa | Alias | | ------------ | ------------------------ | | javascript | js, typescript, ts | | python | py | | go | golang | | lua | — | | bash | sh, shell |

Opsi V2:

| Opsi | Tipe | Default | Deskripsi | | ---------- | -------- | -------------- | ----------------------------------------------------- | | language | string | 'javascript' | Bahasa pemrograman untuk syntax highlighting | | title | string | — | Teks judul yang tampil sebelum code block | | text | string | — | Bagian teks markdown (GenAIMarkdownTextUXPrimitive) | | footer | string | — | Teks footer yang tampil setelah code block |

Jenis Token V2:

| Kode | Nama V1 | Nama V2 | Deskripsi | | ---- | --------- | --------- | --------------------------------------------------------- | | 0 | DEFAULT | DEFAULT | Teks normal, whitespace, operator | | 1 | KEYWORD | KEYWORD | Keyword bahasa (const, func, if, dll.) | | 2 | METHOD | METHOD | Pemanggilan fungsi/method (identifier diikuti () | | 3 | STRING | STR | Literal string ("...", '...', `...`) | | 4 | NUMBER | NUMBER | Nilai numerik (int, float, hex, biner, oktal) | | 5 | COMMENT | COMMENT | Komentar (//, /* */, #) |


Pesan Link (Inline Embed)

Kirim teks kaya dengan link yang dapat diklik secara inline menggunakan placeholder {{IE_N}}display_text{{/IE_N}}, dengan metadata sitasi opsional dan bukti verifikasi.

await sock.sendLink(
  jid,
  "Hasil upload:\n✅ Freeimage\n🔗 Klik: {{IE_0}}link disini{{/IE_0}}\n✅ Yardsansh\n🔗 Klik: {{IE_1}}link disini{{/IE_1}}",
  ["https://example.com/upload1", "https://example.com/upload2"],
  quoted,
  {
    headerText: "📁 Media Uploader V3",
    footer: "✨ Selesai!",
    botJid: "867051314767696@bot",
    forwardingScore: 3,
    citations: [
      {
        sourceTitle: "Freeimage",
        citationNumber: 1,
        faviconCdnUrl: "https://cdn.example.com/favicon.ico",
      },
      { sourceTitle: "Yardsansh", citationNumber: 2 },
    ],
    proofs: [
      {
        version: 1,
        useCase: 1,
        signature: "base64signature==",
        certificateChain: ["base64cert1", "base64cert2"],
      },
    ],
  },
);

Opsi Link:

| Opsi | Tipe | Default | Deskripsi | | ------------------- | ------------ | ------------------------ | ------------------------------------------ | | headerText | string | — | Teks yang tampil sebelum konten link | | footer | string | — | Teks yang tampil setelah konten link | | botJid | string | '867051314767696@bot' | JID bot untuk forwardedAiBotMessageInfo | | forwardingScore | number | 3 | Skor forward untuk context info | | citations | Citation[] | [] | Entri metadata sitasi | | proofs | Proof[] | [] | Entri bukti verifikasi |

Objek Citation:

| Field | Tipe | Deskripsi | | ------------------ | -------- | ---------------------------------------------------- | | sourceQuery | string | Teks query sumber | | faviconCdnUrl | string | URL CDN untuk favicon | | citationNumber | number | Indeks sitasi (otomatis bertambah jika tidak diisi) | | sourceTitle | string | Judul sumber |

Objek Proof:

| Field | Tipe | Deskripsi | | ---------------------- | ---------- | ---------------------------- | | version | number | Versi bukti | | useCase | number | Identifier use case | | signature | string | Signature base64 | | certificateChain | string[] | Rantai sertifikat base64 |

Link V2 (gaya hasil pencarian):

await sock.sendLinkV2(
  jid,
  "Hasil pencarian:\n- {{IE_0}}Dokumentasi resmi{{/IE_0}}\n- {{IE_1}}Repo GitHub{{/IE_1}}",
  [
    {
      url: "https://www.npmjs.com/package/foxxy-baileys",
      displayName: "Dokumentasi resmi",
      sourceDisplayName: "npm",
      sourceSubtitle: "package registry",
    },
    {
      url: "https://github.com/Wanz/foxxy-baileys",
      displayName: "Repo GitHub",
      sourceDisplayName: "github",
      sourceSubtitle: "source hosting",
    },
  ],
  quoted,
  {
    headerText: "foxxy-baileys",
    footer: "Link referensi",
    searchEngine: "MAME",
  },
);

Jenis Pesan Lainnya

Permintaan Pembayaran:

await sock.sendMessage(jid, {
  requestPaymentMessage: {
    amount: 50000,
    currency: "IDR",
    note: "Pembayaran untuk pesanan #123",
    from: "[email protected]",
  },
});

Event:

await sock.sendMessage(jid, {
  eventMessage: {
    name: "Kopdar Komunitas",
    description: "Ayo bergabung di kopdar bulanan kita!",
    startTime: Date.now() + 86400000,
    endTime: Date.now() + 90000000,
    location: {
      name: "Jakarta",
      degreesLatitude: -6.2,
      degreesLongitude: 106.8,
    },
  },
});

Hasil Polling:

await sock.sendMessage(jid, {
  pollResultMessage: {
    name: "Warna Favorit?",
    pollVotes: [
      { optionName: "Merah", optionVoteCount: 42 },
      { optionName: "Biru", optionVoteCount: 38 },
      { optionName: "Hijau", optionVoteCount: 25 },
    ],
  },
});

Status dengan Mention:

await sock.sendStatusMention({ text: "Update besar akan segera hadir!" }, [
  "[email protected]",
  "[email protected]",
]);

Pesan Produk:

await sock.sendMessage(jid, {
  productMessage: {
    title: "Headphone Wireless",
    description: "Headphone bluetooth berkualitas tinggi",
    productId: "WH-001",
    retailerId: "foxxy-shop",
    url: "https://example.com/product",
    priceAmount1000: 299000,
    currencyCode: "IDR",
    thumbnail: { url: "https://example.com/product.jpg" },
    body: "Lihat produk ini!",
    footer: "Foxxy Shop",
    buttons: [
      {
        name: "quick_reply",
        buttonParamsJson: JSON.stringify({
          display_text: "Beli Sekarang",
          id: "buy_wh001",
        }),
      },
    ],
  },
});

Pesan Kaya Campuran (submessage kustom):

await sock.sendRichMessage(
  jid,
  [
    { messageType: 2, messageText: "Berikut beberapa info:" },
    {
      messageType: 4,
      tableMetadata: {
        title: "Statistik",
        rows: [
          { items: ["Metrik", "Nilai"], isHeading: true },
          { items: ["Pengguna", "1000"] },
          { items: ["Uptime", "99.9%"] },
        ],
      },
    },
    { messageType: 2, messageText: "Dan sedikit kode:" },
    {
      messageType: 5,
      codeMetadata: {
        codeLanguage: "javascript",
        codeBlocks: [{ highlightType: 0, codeContent: 'console.log("OK")' }],
      },
    },
  ],
  quoted,
);

Jenis SubMessage:

| messageType | Nama | Field Payload | | ----------- | ------------- | -------------------------- | | 0 | UNKNOWN | — | | 1 | GRID_IMAGE | gridImageMetadata | | 2 | TEXT | messageText | | 3 | INLINE_IMAGE | imageMetadata | | 4 | TABLE | tableMetadata | | 5 | CODE | codeMetadata | | 6 | DYNAMIC | dynamicMetadata | | 7 | MAP | mapMetadata | | 8 | LATEX | latexMetadata | | 9 | CONTENT_ITEMS | contentItemsMetadata |


Metode Newsletter

// Resolve URL channel menjadi metadata
const info = await sock.cekIDSaluran("https://whatsapp.com/channel/xxxxx");
console.log(info.name, info.subscribers);

// Follow banyak channel sekaligus
await sock.newsletterMultipleFollow("id1@newsletter id2@newsletter");

// Ambil semua channel yang di-subscribe
const channels = await sock.newsletterFetchAllSubscribe();

// Aksi generik (follow/unfollow/mute/unmute)
await sock.newsletterAction("id@newsletter", "follow");

// Buat newsletter
const nl = await sock.newsletterCreate("Channel Saya", "Deskripsi");

// Update newsletter
await sock.newsletterUpdate("id@newsletter", { name: "Nama Baru" });

// Ambil jumlah subscriber
const { subscribers } = await sock.newsletterSubscribers("id@newsletter");

// Ambil metadata
const meta = await sock.newsletterMetadata("jid", "id@newsletter");

// Follow / Unfollow
await sock.newsletterFollow("id@newsletter");
await sock.newsletterUnfollow("id@newsletter");

// Mute / Unmute
await sock.newsletterMute("id@newsletter");
await sock.newsletterUnmute("id@newsletter");

// Update nama / deskripsi / gambar
await sock.newsletterUpdateName("id@newsletter", "Nama Baru");
await sock.newsletterUpdateDescription("id@newsletter", "Deskripsi Baru");
await sock.newsletterUpdatePicture("id@newsletter", mediaUpload);
await sock.newsletterRemovePicture("id@newsletter");

// React ke pesan
await sock.newsletterReactMessage("id@newsletter", serverId, "👍");

// Ambil pesan
const msgs = await sock.newsletterFetchMessages("id@newsletter", 50, 0, 0);

// Operasi admin
const count = await sock.newsletterAdminCount("id@newsletter");
await sock.newsletterChangeOwner("id@newsletter", newOwnerJid);
await sock.newsletterDemote("id@newsletter", userJid);
await sock.newsletterDelete("id@newsletter");

Metode Grup

// Ambil metadata grup
const meta = await sock.groupMetadata("[email protected]");

// Buat grup
const group = await sock.groupCreate("Grup Saya", ["[email protected]"]);

// Keluar dari grup
await sock.groupLeave("[email protected]");

// Update subjek / deskripsi
await sock.groupUpdateSubject("[email protected]", "Subjek Baru");
await sock.groupUpdateDescription("[email protected]", "Deskripsi Baru");

// Aksi partisipan: add, remove, promote, demote
const result = await sock.groupParticipantsUpdate(
  "[email protected]",
  ["[email protected]"],
  "add", // 'remove' | 'promote' | 'demote'
);

// Menangani permintaan gabung
const requests = await sock.groupRequestParticipantsList("[email protected]");
await sock.groupRequestParticipantsUpdate(
  "[email protected]",
  ["[email protected]"],
  "approve",
);

// Kode undangan
const code = await sock.groupInviteCode("[email protected]");
await sock.groupRevokeInvite("[email protected]");
await sock.groupAcceptInvite("ABCDE12345");
const info = await sock.groupGetInviteInfo("ABCDE12345");

// Pengaturan: announcement, not_announcement, locked, unlocked
await sock.groupSettingUpdate("[email protected]", "announcement");
await sock.groupSettingUpdate("[email protected]", "locked");

// Mode tambah anggota / Persetujuan gabung
await sock.groupMemberAddMode("[email protected]", "admin_add");
await sock.groupJoinApprovalMode("[email protected]", "on");

// Toggle pesan sekali lihat/hilang
await sock.groupToggleEphemeral("[email protected]", 86400); // 24 jam

// Ambil semua grup yang diikuti
const groups = await sock.groupFetchAllParticipating();

// Update label anggota
await sock.updateMemberLabel("[email protected]", "VIP");

Metode Komunitas

// Ambil metadata komunitas
const meta = await sock.communityMetadata("[email protected]");

// Buat komunitas
const community = await sock.communityCreate(
  "Komunitas Kita",
  "Deskripsi komunitas",
);

// Buat subgroup di bawah komunitas
const subgroup = await sock.communityCreateGroup(
  "Pengumuman",
  ["[email protected]"],
  "[email protected]",
);

// Tautkan / lepas tautan grup yang sudah ada
await sock.communityLinkGroup("[email protected]", "[email protected]");
await sock.communityUnlinkGroup("[email protected]", "[email protected]");

// Ambil grup yang tertaut
const linked = await sock.communityFetchLinkedGroups("[email protected]");

// Penanganan undangan
const code = await sock.communityInviteCode("[email protected]");
await sock.communityRevokeInvite("[email protected]");
await sock.communityAcceptInvite(code);
const inviteInfo = await sock.communityGetInviteInfo(code);

// Permintaan / partisipan
const requests =
  await sock.communityRequestParticipantsList("[email protected]");
await sock.communityRequestParticipantsUpdate(
  "[email protected]",
  ["[email protected]"],
  "approve",
);
await sock.communityParticipantsUpdate(
  "[email protected]",
  ["[email protected]"],
  "add",
);

// Pengaturan
await sock.communityUpdateSubject("[email protected]", "Subjek Baru");
await sock.communityUpdateDescription("[email protected]", "Deskripsi Baru");
await sock.communityToggleEphemeral("[email protected]", 86400);
await sock.communitySettingUpdate("[email protected]", "announcement");
await sock.communityMemberAddMode("[email protected]", "admin_add");
await sock.communityJoinApprovalMode("[email protected]", "on");

// Keluar / daftar semua
await sock.communityLeave("[email protected]");
const communities = await sock.communityFetchAllParticipating();

Metode Bisnis

// Katalog
const { products, nextPageCursor } = await sock.getCatalog({
  jid: "[email protected]",
  limit: 10,
});

const { collections } = await sock.getCollections("[email protected]", 10);

// Pesanan
const order = await sock.getOrderDetails(orderId, tokenBase64);

// CRUD Produk
const product = await sock.productCreate({
  name: "Paket Premium",
  description: "Paket premium resmi",
  price: 150000,
  currency: "IDR",
  originCountryCode: "ID",
  images: [mediaUpload],
});

await sock.productUpdate(product.id, {
  name: "Paket Premium Plus",
  description: "Paket premium resmi plus",
  price: 175000,
  currency: "IDR",
  images: [mediaUpload],
});

await sock.productDelete([product.id]);

// Profil bisnis
await sock.updateBusinessProfile({
  address: "Jakarta, Indonesia",
  description: "Toko resmi",
  websites: ["https://example.com"],
  email: "[email protected]",
  hours: {
    timezone: "Asia/Jakarta",
    days: [{ day: "mon", mode: "open_24h" }],
  },
});

// Alias lama tetap tersedia untuk kompatibilitas ke belakang
await sock.updateBussinesProfile({
  description: "Alias lama tetap berfungsi",
});

await sock.updateCoverPhoto(mediaUpload);
await sock.removeCoverPhoto(coverId);

// Balasan cepat
await sock.addOrEditQuickReply({
  shortcut: "hello",
  message: "Halo dari akun bisnis",
});

await sock.removeQuickReply(timestamp);

Metode Chat & Profil

// Foto profil
const url = await sock.profilePictureUrl(jid, "image");
await sock.updateProfilePicture(jid, mediaUpload);
await sock.removeProfilePicture(jid);

// Nama profil / status
await sock.updateProfileName("Nama Saya");
await sock.updateProfileStatus("Tersedia");

// Presence
await sock.sendPresenceUpdate("available", jid);
await sock.presenceSubscribe(jid);

// Read receipt
await sock.readMessages([msg.key]);
await sock.sendReceipt(jid, participant, [msgId], "read");

// Block / Unblock
await sock.updateBlockStatus(jid, "block");
await sock.updateBlockStatus(jid, "unblock");

// Ambil daftar blokir
const list = await sock.fetchBlocklist();

// Modifikasi chat
await sock.chatModify(
  {
    archive: true,
    lastMessageOrig: msg,
    lastMessage: msg,
  },
  jid,
);

// Bintangi pesan
await sock.star(jid, [{ id: msgId, fromMe: true }], true);

// Manajemen kontak
await sock.addOrEditContact(jid, { displayName: "Nama" });
await sock.removeContact(jid);

// Label
await sock.addChatLabel(jid, labelId);
await sock.removeChatLabel(jid, labelId);
await sock.addMessageLabel(jid, messageId, labelId);

// Sinkronisasi app state
await sock.resyncAppState(["regular", "critical_block"], true);

// Profil bisnis
const biz = await sock.getBusinessProfile(jid);

Pengaturan Privasi

await sock.updateLastSeenPrivacy("all"); // 'all' | 'contacts' | 'contact_blacklist' | 'nobody'
await sock.updateOnlinePrivacy("all"); // 'all' | 'match_last_seen'
await sock.updateProfilePicturePrivacy("contacts");
await sock.updateStatusPrivacy("contacts");
await sock.updateReadReceiptsPrivacy("all"); // 'all' | 'none'
await sock.updateGroupsAddPrivacy("all"); // 'all' | 'contacts'
await sock.updateMessagesPrivacy("all"); // 'all' | 'contacts' | 'nobody'
await sock.updateCallPrivacy("everyone");
await sock.updateDefaultDisappearingMode(86400);
await sock.updateDisableLinkPreviewsPrivacy(true);

📡 Referensi Event

sock.ev.on('connection.update', ({ connection, lastDisconnect, qr, isNewLogin, receivedPendingNotifications, isOnline }) => {})
sock.ev.on('creds.update', (update) => {})
sock.ev.on('messaging-history.set', ({ chats, contacts, messages, isLatest }) => {})
sock.ev.on('chats.upsert', (chats) => {})
sock.ev.on('chats.update', (updates) => {})
sock.ev.on('chats.delete', (jids) => {})
sock.ev.on('contacts.upsert', (contacts) => {})
sock.ev.on('contacts.update', (updates) => {})
sock.ev.on('messages.upsert', ({ messages, type }) => {})
sock.ev.on('messages.update', (updates) => {})
sock.ev.on('messages.delete', (keys) => {})
sock.ev.on('messages.reaction', (reactions) => {})
sock.ev.on('message-receipt.update', (updates) => {})
sock.ev.on('groups.update', (updates) => {})
sock.ev.on('group-participants.update', (update) => {})
sock.ev.on('group.join-request', (update) => {})
sock.ev.on('call', (calls) => {})
sock.ev.on('labels.edit', (label) => {})
sock.ev.on('labels.associations', ({ associated, label, type }) => {})
sock.ev.on('newsletter.update', (updates) => {})
sock.ev.on('newsletter.follow', (jid) => {})
sock.ev.on('newsletter.unfollow', (jid) => {})
sock.ev.on('settings.update', ({ isAutoEmojiEnabled, isReadReceiptsEnabled, ... }) => {})

🔧 Ekspor Utilitas

import {
  // Auth
  useMultiFileAuthState,
  makeCacheableSignalKeyStore,
  initAuthCreds,
  BufferJSON,
  fetchLatestBaileysVersion,

  // Tokenisasi kode
  tokenizeCode,
  tokenizeCodeV2,
  CodeHighlightType,
  RichSubMessageType,

  // Generator pesan kaya
  generateTableContent,
  generateTableContentV2,
  toTableMetadataV2,
  generateListContent,
  generateCodeBlockContent,
  generateCodeBlockContentV2,
  generateLinkContent,
  generateLinkContentV2,
  generateRichMessageContent,
  generateLatexContent,
  generateLatexImageContent,
  generateLatexInlineImageContent,
  generateUnifiedResponseContent,
  captureUnifiedResponse,

  // Pembuat pesan kaya
  buildRichContextInfo,
  buildBotForwardedMessage,

  // Helper paket stiker
  makeStickerPack,

  // Kumpulan keyword bahasa
  JS_KEYWORDS,
  PYTHON_KEYWORDS,
  GO_KEYWORDS,
  LUA_KEYWORDS,
  BASH_KEYWORDS,
  LANGUAGE_KEYWORDS,

  // Kripto
  Curve,
  signedKeyPair,
  aesEncryptGCM,
  aesDecryptGCM,

  // Utilitas JID
  jidEncode,
  jidDecode,
  jidNormalizedUser,
  areJidsSameUser,
  isJidGroup,
  isJidNewsletter,
  isLidUser,
  isPnUser,
  isJidBot,
  isJidMetaAI,
  isJidBroadcast,
  isJidStatusBroadcast,

  // Koneksi
  DisconnectReason,
  Browsers,

  // Dugong (jenis pesan lanjutan)
  Dugong,

  // Tipe
  WASocket,
} from "foxxy-baileys";

[!NOTE] Pada build ini, beberapa typing helper lanjutan mungkin muncul lebih dulu di lib/Socket/messages-send.d.ts sebelum tercermin di tempat lain pada deklarasi socket gabungan. Jika autocomplete editor Anda tertinggal dari perilaku runtime, periksa lib/Socket/messages-send.js dan lib/Utils/rich-messages.d.ts untuk permukaan helper yang paling lengkap.


🏗️ Mem-build Paket Ini

Repositori ini menyediakan file hasil kompilasi, namun tetap menyertakan skrip build yang digunakan untuk menghasilkan/memperbarui lib/.

npm install
npm run build

Yang dilakukan proses build:

  • menjalankan TypeScript dengan tsconfig.build.json
  • menghasilkan file JavaScript dan file deklarasi ke dalam lib/
  • menjalankan tsc-esm-fix agar import ESM yang dihasilkan ter-resolve dengan bersih

Catatan build penting:

  • tsconfig.json berorientasi penulisan dan menggunakan noEmit: true
  • tsconfig.build.json mengaktifkan kembali emit dan mengecualikan file test
  • file paket yang terpublikasi dibatasi pada lib/**/* dan WAProto/**/*

🔀 Perbedaan dengan Baileys Resmi

| Area | Baileys Resmi v7 | foxxy-baileys | | ------------------------ | -------------------- | --------------------------------------------- | | Pesan interaktif | Tidak ada dukungan native | Dukungan penuh via Dugong | | Pesan album | Tidak didukung | Album multi-media | | Respons Kaya AI | Tidak tersedia | Tabel, code block, teks kaya | | Table V1 | Tidak tersedia | Tabel dasar dengan header | | Table V2 | Tidak tersedia | Respons terpadu + GenATableUXPrimitive | | Code Block V1 | Tidak tersedia | Syntax highlighting (JS/TS/Python) | | Code Block V2 | Tidak tersedia | Respons terpadu + 6 bahasa | | Pesan Link | Tidak tersedia | Embed inline + sitasi + verifikasi | | Node bisnis | Injeksi manual | Auto-inject saat relay | | Ekstra newsletter | Hanya dasar | Auto-follow, follow massal, resolve URL | | Deteksi tombol | Tidak tersedia | Auto-detect getButtonType() | | Pesan pembayaran | Tidak didukung | Dukungan penuh | | Pesan event | Dasar | Semua field ditingkatkan | | Mention status | Tidak tersedia | sendStatusMention() | | Pesan produk | Tidak didukung | Katalog + tombol | | Dukungan LID | Dasar | Pemetaan LID↔PN penuh + migrasi sesi | | Perubahan identitas | Tidak ditangani | Refresh sesi dengan debounce | | Retry pesan | Dasar | MessageRetryManager dengan cache |


🤝 Berkontribusi

  1. Fork repo ini
  2. Buat branch (git checkout -b feature/nama)
  3. Commit perubahan (git commit -m 'feat: menambahkan fitur')
  4. Push ke branch (git push origin feature/nama)
  5. Buka Pull Request

📄 Lisensi

MIT © Wanz

[!CAUTION] Library ini ditujukan untuk tujuan edukasi. Pastikan kepatuhan terhadap Ketentuan Layanan WhatsApp.


Dibuat dengan 💚 oleh Wanz

⭐ Beri bintang repo ini · 🐛 Laporkan Bug · 💡 Ajukan Fitur