foxxy-baileys
v0.0.1
Published
Baileys v7 modifikasi dengan dukungan pesan interaktif, album, dan newsletter
Maintainers
Readme
Baileys Modifikasi — Pesan Interaktif, Respons Kaya AI, Album & Lainnya
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.jsdi mana error "Bad MAC" / dekripsi dapat menutup koneksi. Dikombinasikan dengan hookgetMessageyang 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 dariAIRichpadamessage_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
- foxxy-baileys
✨ 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"dipackage.jsonAnda) - Implementasi penyimpanan auth yang persisten untuk penggunaan produksi
- Helper opsional tergantung kebutuhan Anda:
pinountuk loggingqrcode-terminaljika Anda ingin merender kode QR di terminal sendirisharp,jimp,audio-decode,link-preview-jsuntuk utilitas media/kaya opsional
[!IMPORTANT]
foxxy-baileyshanya 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-baileysPaket pendamping yang direkomendasikan untuk contoh di README ini:
npm install pino qrcode-terminalMenggunakan Alias (Direkomendasikan untuk Bot Foxxy-MD)
Tambahkan ke package.json:
{
"dependencies": {
"foxxy": "npm:foxxy-baileys@latest"
}
}Lalu jalankan:
npm install[!TIP] Menggunakan alias
foxxymemungkinkan Anda melakukanimport foxxy from 'foxxy'tanpa mengubah kode yang sudah ada.
[!NOTE] Peer dependency seperti
sharp,jimp,audio-decode, danlink-preview-jsbersifat opsional. Instal hanya yang dibutuhkan fitur bot Anda.
🛠️ Mulai Cepat
1. Setup Proyek
mkdir bot-saya && cd bot-saya
npm init -yPastikan 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-terminal3. 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.jsPindai 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]
printQRInTerminalmasih ada pada permukaan tipe untuk kompatibilitas, namun sudah usang (deprecated) pada build saat ini. Sebaiknya tangani sendiri nilaiqrdariconnection.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 TERATASModul 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.jslib/index.d.tslib/Socket/*.d.tslib/Utils/*.d.ts
- Pengguna sebaiknya memperlakukan repo ini sebagai artefak runtime siap-instal, bukan tree sumber penulisan
Alur Koneksi
- Koneksi WebSocket → handshake Noise XX (Curve25519 + AES-256-GCM)
- Autentikasi kode QR atau kode Pairing
CB:success→ unggah pre-key → kirim IQ pasif → emitconnection: 'open'- Simpan pemetaan LID↔PN milik sendiri, migrasi sesi sendiri
- 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 diskPola 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/lokalinitAuthCreds()+SignalKeyStorekustom untuk persistensi DB/Redis/in-memorymakeCacheableSignalKeyStore()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
expectedImageCountdanexpectedVideoCountberdasarkan 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) contextInfoyang ditingkatkan denganbotMessageSharingInfo
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 judultable[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:
codeBlocknumerik +unified_codeBlockbertipe string - Bagian respons terpadu dengan typename
GenAICodeUXPrimitive/GenAIMarkdownTextUXPrimitive contextInfoyang ditingkatkan denganbotMessageSharingInfo
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.tssebelum tercermin di tempat lain pada deklarasi socket gabungan. Jika autocomplete editor Anda tertinggal dari perilaku runtime, periksalib/Socket/messages-send.jsdanlib/Utils/rich-messages.d.tsuntuk 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 buildYang dilakukan proses build:
- menjalankan TypeScript dengan
tsconfig.build.json - menghasilkan file JavaScript dan file deklarasi ke dalam
lib/ - menjalankan
tsc-esm-fixagar import ESM yang dihasilkan ter-resolve dengan bersih
Catatan build penting:
tsconfig.jsonberorientasi penulisan dan menggunakannoEmit: truetsconfig.build.jsonmengaktifkan kembali emit dan mengecualikan file test- file paket yang terpublikasi dibatasi pada
lib/**/*danWAProto/**/*
🔀 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
- Fork repo ini
- Buat branch (
git checkout -b feature/nama) - Commit perubahan (
git commit -m 'feat: menambahkan fitur') - Push ke branch (
git push origin feature/nama) - Buka Pull Request
📄 Lisensi
MIT © Wanz
[!CAUTION] Library ini ditujukan untuk tujuan edukasi. Pastikan kepatuhan terhadap Ketentuan Layanan WhatsApp.
Dibuat dengan 💚 oleh Wanz
