ascbail
v1.0.0
Published
Enhanced Baileys v1 by PT.ASCIN DIGITAL NUSANTARA with fixes for newsletter media uploads, plus support for interactive messages, albums, and additional message types.
Maintainers
Readme
ascbail
Informasi
Ascbail -- Modifikasi Baileys yang dikelola oleh PT.ASCIN DIGITAL NUSANTARA.
| Media | Tautan | |-------|--------| | GitHub | github.com/ndradev | | Website | www.ascin.id | | Email Perusahaan | [email protected] | | Email Owner | [email protected] | | WhatsApp | wa.me/6287767867841 | | Instagram | instagram.com/ascin.id | | TikTok | ascin.id | | Founder/CEO | Ndra Developer (NdraCloudHost) | | Instagram Owner | instagram.com/dra.lpnm_ | | Telegram Owner | dradevid | | Donasi | donate.ascin.xyz |
Keunggulan
Fork ini dirancang untuk penggunaan production dengan fokus pada kejelasan dan keamanan:
- Tanpa obfuscation -- mudah dibaca dan diaudit.
- Tidak ada perilaku auto-follow channel (newsletter).
[!IMPORTANT] Proyek ini didasarkan pada ascbail yang dilisensikan di bawah MIT. Kredit dan rasa hormat sepenuhnya diberikan kepada penulis asli Lia Wynn dan maintainer Baileys upstream di WhiskeySockets/Baileys.
[!NOTE] Proyek ini dikelola dengan lingkup terbatas dan tidak dimaksudkan untuk menggantikan Baileys upstream.
Daftar Isi
- Keunggulan
- Penyesuaian Internal
- Penanganan & Kompatibilitas Pesan
- Opsi Pesan Tambahan
- Instalasi
- Koneksi ke WhatsApp (Langkah Cepat)
- Implementasi Data Store
- Penjelasan ID WhatsApp
- Mengirim Pesan
- Mengirim Media
- Mengirim Pesan Interaktif
- Mengirim Pesan Pembayaran
- Opsi Pesan Lainnya
- Modifikasi Pesan
- Konten Tambahan
- Fork Base
- Kredit
Penyesuaian Internal
- Memperbaiki masalah pengiriman media ke newsletter akibat issue upstream.
- Mengenalkan kembali
makeInMemoryStoredengan adaptasi ESM minimal dan penyesuaian kecil untuk Baileys v7. - Mengubah eksekusi FFmpeg dari
execkespawnuntuk penanganan proses yang lebih aman. - Menambahkan
@napi-rs/imagesebagai backend pemrosesan gambar yang didukung digetImageProcessingLibrary(), menawarkan keseimbangan antara performa dan kompatibilitas.
Penanganan & Kompatibilitas Pesan
- Dukungan pesan yang diperluas untuk:
- Album Message
- Group Status Message
- Interactive Message (buttons, lists, native flows, templates, carousels)
- Status Mention Message
- Sticker Pack Message
- Rich Response Message -- BARU
- Message with Code Blocks -- BARU
- Message with Inline Entities -- BARU
- Message with Table -- BARU
- Payment-related Message (payment requests, invites, orders, invoices)
- Menyederhanakan pengiriman pesan dengan thumbnail iklan menggunakan
externalAdReply, tanpa memerlukancontextInfomanual. - Menambahkan dukungan untuk mengutip pesan di dalam channel (newsletter). -- BARU
- Menambahkan dukungan untuk custom button icon. -- BARU
Opsi Pesan Tambahan
- Menambahkan flag boolean opsional untuk penanganan pesan:
ai-- Ikon AI pada pesanmentionAll-- Mention semua peserta grup tanpa memerlukan JID dimentionsataumentionedJid-- BARUephemeral,groupStatus,isLottie,spoiler,viewOnce,viewOnceV2,viewOnceV2Extension,interactiveAsTemplate-- Pembungkus pesansecureMetaServiceLabel-- Label layanan meta aman pada pesan -- BARUraw-- Bangun pesan secara manual (JANGAN GUNAKAN UNTUK EKSPLOITASI)
Instalasi
Melalui package.json:
# NPM
"dependencies": {
"ascbail": "latest"
}
# GitHub
"dependencies": {
"ascbail": "github:NdraDev/ascbail"
}Melalui terminal:
# NPM
npm i ascbail@latest
# GitHub
npm i github:NdraDev/ascbailImport (ESM & CJS)
// --- ESM
import { makeWASocket } from 'ascbail'
// --- CJS (teruji dan berfungsi di Node.js 24)
const { makeWASocket } = require('ascbail')Koneksi ke WhatsApp (Langkah Cepat)
import { makeWASocket, delay, DisconnectReason, useMultiFileAuthState } from 'ascbail'
import { Boom } from '@hapi/boom'
import pino from 'pino'
// --- Connect dengan pairing code
const myPhoneNumber = '6288888888888'
const logger = pino({ level: 'silent' })
const connectToWhatsApp = async () => {
const { state, saveCreds } = await useMultiFileAuthState('session')
const sock = makeWASocket({
logger,
auth: state
})
sock.ev.on('creds.update', saveCreds)
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update
if (connection === 'connecting' && !sock.authState.creds.registered) {
await delay(1500)
const code = await sock.requestPairingCode(myPhoneNumber)
console.log('Pairing code:', code)
}
else if (connection === 'close') {
const shouldReconnect = new Boom(connection?.lastDisconnect?.error)?.output?.statusCode !== DisconnectReason.loggedOut
console.log('Koneksi terputus karena', lastDisconnect.error, ', reconnecting:', shouldReconnect)
if (shouldReconnect) {
connectToWhatsApp()
}
}
else if (connection === 'open') {
console.log('Berhasil terhubung ke WhatsApp')
}
})
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const message of messages) {
if (!message.message) continue
console.log('Pesan baru diterima:', message)
await sock.sendMessage(message.key.remoteJid, {
text: 'Halo dunia'
})
}
})
}
connectToWhatsApp()Auth State
[!NOTE] Anda dapat menggunakan
useSingleFileAuthStatedanuseSqliteAuthState(eksperimental) sebagai alternatif dariuseMultiFileAuthState. Namun,useSingleFileAuthStatesudah memiliki mekanisme caching internal, sehingga tidak perlu membungkusstate.keysdenganmakeCacheableSignalKeyStore.
Implementasi Data Store
[!CAUTION] Sangat disarankan untuk membangun data store Anda sendiri, karena menyimpan seluruh riwayat chat di memori dapat menyebabkan penggunaan RAM yang berlebihan.
import { makeWASocket, makeInMemoryStore, delay, DisconnectReason, useMultiFileAuthState } from 'ascbail'
import { Boom } from '@hapi/boom'
import pino from 'pino'
const myPhoneNumber = '6288888888888'
// --- Tentukan path penyimpanan store
const storePath = './store.json'
const logger = pino({ level: 'silent' })
const connectToWhatsApp = async () => {
const { state, saveCreds } = await useMultiFileAuthState('session')
const sock = makeWASocket({
logger,
auth: state
})
const store = makeInMemoryStore({
logger,
socket: sock
})
store.bind(sock.ev)
sock.ev.on('creds.update', saveCreds)
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update
if (connection === 'connecting' && !sock.authState.creds.registered) {
await delay(1500)
const code = await sock.requestPairingCode(myPhoneNumber)
console.log('Pairing code:', code)
}
else if (connection === 'close') {
const shouldReconnect = new Boom(connection?.lastDisconnect?.error)?.output?.statusCode !== DisconnectReason.loggedOut
console.log('Koneksi terputus karena', lastDisconnect.error, ', reconnecting:', shouldReconnect)
if (shouldReconnect) {
connectToWhatsApp()
}
}
else if (connection === 'open') {
console.log('Berhasil terhubung ke WhatsApp')
}
})
sock.ev.on('chats.upsert', () => {
console.log('Chats tersedia:', store.chats.all())
})
sock.ev.on('contacts.upsert', () => {
console.log('Kontak tersedia:', Object.values(store.contacts))
})
// --- Baca store dari file
store.readFromFile(storePath)
// --- Simpan store setiap 3 menit
setInterval(() => {
store.writeToFile(storePath)
}, 180000)
}
connectToWhatsApp()Penjelasan ID WhatsApp
id adalah ID WhatsApp, disebut juga jid dan lid, dari orang atau grup yang Anda kirimi pesan.
- Format:
[kode negara][nomor telepon]@s.whatsapp.net- Contoh untuk individu:
[email protected]dan12699999999@lid - Untuk grup:
[email protected]
- Contoh untuk individu:
- Untuk Meta AI:
11111111111@bot - Untuk broadcast list:
[timestamp pembuatan]@broadcast - Untuk status/story:
status@broadcast
Mengirim Pesan
[!NOTE] Anda bisa mendapatkan
jiddarimessage.key.remoteJidpada contoh pertama.
Teks
// --- Kirim pesan teks biasa
sock.sendMessage(jid, {
text: 'Halo'
}, {
quoted: message
})
// --- Kirim pesan teks dengan pratinjau tautan
const urlA = 'https://github.com/NdraDev/ascbail'
sock.sendMessage(jid, {
text: urlA + ' - Cek tautannya!',
linkPreview: {
'matched-text': urlA,
title: 'bailcin',
description: 'Bailcin - Modifikasi Baileys',
previewType: 0, // --- Gunakan 1 untuk pemutaran video di pratinjau tautan
jpegThumbnail: fs.readFileSync('./path/to/image.jpg')
}
})
// --- Kirim pesan teks dengan pratinjau tautan besar dan favicon
import { prepareWAMessageMedia } from 'ascbail'
const urlB = 'https://github.com/NdraDev/ascbail#readme'
const { imageMessage: image } = await prepareWAMessageMedia({
image: {
url: './path/to/image.jpg'
}
}, {
upload: sock.waUploadToServer,
mediaTypeOverride: 'thumbnail-link'
})
// --- Atur ukuran tampilan thumbnail
image.height = 720
image.width = 480
sock.sendMessage(jid, {
text: urlB + ' - Cek tautannya!',
linkPreview: {
'matched-text': urlB,
title: 'bailcin',
description: 'Bailcin - Modifikasi Baileys',
previewType: 0,
jpegThumbnail: fs.readFileSync('./path/to/image.jpg'),
highQualityThumbnail: image,
linkPreviewMetadata: {
linkMediaDuration: 0, // --- Durasi dalam detik (untuk konten video/audio)
socialMediaPostType: 1, // --- Enum: 0 = NONE, 1 = REEL, 2 = LIVE_VIDEO, 3 = LONG_VIDEO, 4 = SINGLE_IMAGE, 5 = CAROUSEL
} // --- Metadata tambahan untuk pratinjau tautan besar
},
favicon: {
url: './path/to/tiny-image.ico'
}
})Mention
// --- Mention biasa
sock.sendMessage(jid, {
text: 'Halo @628123456789',
mentions: ['[email protected]']
}, {
quoted: message
})
// --- Mention semua anggota
sock.sendMessage(jid, {
text: 'Halo @all',
mentionAll: true
}, {
quoted: message
})Reaksi
sock.sendMessage(jid, {
react: {
key: message.key,
text: '👍'
}
})Pin Pesan
sock.sendMessage(jid, {
pin: message.key,
time: 86400, // --- Nilai dalam detik: 86400 (1h), 604800 (7h), atau 2592000 (30h)
type: 1 // --- Atau 2 untuk menghapus pin
})Keep Chat
[!NOTE] Keep Chat hanya dapat digunakan di chat atau grup dengan pesan sementara yang diaktifkan.
sock.sendMessage(jid, {
keep: message.key,
type: 1 // --- Atau 2 untuk menghapus
})Forward Pesan
sock.sendMessage(jid, {
forward: message,
force: true // --- Opsional
})Kontak
const vcard = 'BEGIN:VCARD\n'
+ 'VERSION:3.0\n'
+ 'FN:Lia Wynn\n'
+ 'ORG:Waitress;\n'
+ 'TEL;type=CELL;type=VOICE;waid=628123456789:+62 8123 4567 89\n'
+ 'END:VCARD'
sock.sendMessage(jid, {
contacts: {
displayName: 'Lia Wynn',
contacts: [
{ vcard }
]
}
}, {
quoted: message
})Lokasi
sock.sendMessage(jid, {
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221,
name: 'Saya di sini'
}
}, {
quoted: message
})Event
sock.sendMessage(jid, {
event: {
name: 'Meet & Mingle Party',
description: 'Acara santai untuk terhubung, mengobrol, dan membangun hubungan baru dalam komunitas.',
call: 'audio', // --- Atau "video", field ini opsional
startDate: new Date(Date.now() + 3600000),
endDate: new Date(Date.now() + 28800000),
isCancelled: false, // --- Opsional
isScheduleCall: false, // --- Opsional
extraGuestsAllowed: false, // --- Opsional
location: {
name: 'Jakarta',
degreesLatitude: -6.2,
degreesLongitude: 106.8
}
}
}, {
quoted: message
})Undangan Grup
const inviteCode = groupUrl
.split('chat.whatsapp.com/')[1]
?.split('?')[0]
const groupJid = '[email protected]'
const groupName = 'bailcin'
sock.sendMessage(jid, {
groupInvite: {
inviteCode,
inviteExpiration: Date.now() + 86400000,
text: 'Halo, kami mengundang Anda untuk bergabung dengan grup kami.',
jid: groupJid,
subject: groupName,
}
}, {
quoted: message
})Product
import { randomUUID } from 'crypto'
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
body: 'Lihat produk saya di sini!',
footer: 'bailcin',
product: {
currencyCode: 'IDR',
description: 'Produk menarik!',
priceAmount1000: 70_000_000,
productId: randomUUID(),
productImageCount: 1,
salePriceAmount1000: 65_000_000,
signedUrl: 'https://github.com/ndradev/bailcin',
title: 'Bailcin (Premium)',
url: 'https://github.com/ndradev/bailcin'
},
businessOwnerJid: '[email protected]'
})Poll
// --- Poll biasa
sock.sendMessage(jid, {
poll: {
name: 'Waktunya voting',
values: ['Ya', 'Tidak'],
selectableCount: 1,
toAnnouncementGroup: false,
endDate: new Date(Date.now() + 28800000), // --- Opsional
hideVoter: false, // --- Opsional
canAddOption: false // --- Opsional
}
}, {
quoted: message
})
// --- Kuis (khusus newsletter)
sock.sendMessage('1211111111111@newsletter', {
poll: {
name: 'Kuis',
values: ['Ya', 'Tidak'],
correctAnswer: 'Ya',
pollType: 1
}
}, {
quoted: message
})
// --- Hasil Poll
sock.sendMessage(jid, {
pollResult: {
name: 'Hasil Poll',
votes: [{
name: 'Bagus',
voteCount: 10
}, {
name: 'Kurang',
voteCount: 2
}],
pollType: 0 // Atau 1 untuk kuis
}
}, {
quoted: message
})
// --- Update Poll
sock.sendMessage(jid, {
pollUpdate: {
metadata: {},
key: message.key,
vote: {
enclv: /* <Buffer> */,
encPayload: /* <Buffer> */
}
}
}, {
quoted: message
})Button Response
// --- Menggunakan buttonsResponseMessage
sock.sendMessage(jid, {
type: 'plain',
buttonReply: {
id: '#Menu',
displayText: 'Menu Menarik'
}
}, {
quoted: message
})
// --- Menggunakan interactiveResponseMessage
sock.sendMessage(jid, {
flowReply: {
format: 0,
text: 'Respon',
name: 'menu_options',
paramsJson: JSON.stringify({
id: '#Menu',
description: 'Menu Menarik'
})
}
}, {
quoted: message
})
// --- Menggunakan listResponseMessage
sock.sendMessage(jid, {
listReply: {
title: 'Lihat Lainnya',
description: 'Menu Menarik',
id: '#Menu'
}
}, {
quoted: message
})
// --- Menggunakan templateButtonReplyMessage
sock.sendMessage(jid, {
type: 'template',
buttonReply: {
id: '#Menu',
displayText: 'Menu Menarik',
index: 1
}
}, {
quoted: message
})Rich Response
[!NOTE]
richResponse[]adalah representasi darisubmessages[]di dalamrichResponseMessage.
[!TIP] Anda masih bisa menggunakan field
submessages[]asli secara langsung. Contoh kode di bawah hanyalah implementasi menggunakan helper, bukan struktur yang diwajibkan.
sock.sendMessage(jid, {
disclaimerText: 'Contoh struktur submessages mentah',
richResponse: [{
text: 'Contoh Penggunaan',
}, {
language: 'javascript',
code: [{
highlightType: 0,
codeContent: 'console.log("Hello, World!")'
}]
}, {
text: 'Cukup sederhana, bukan?\n'
}, {
text: 'Perbandingan antara Node.js, Bun, dan Deno',
}, {
title: 'Perbandingan Runtime',
table: [{
isHeading: true,
items: ['', 'Node.js', 'Bun', 'Deno']
}, {
isHeading: false,
items: ['Engine', 'V8 (C++)', 'JavaScriptCore (C++)', 'V8 (C++)']
}, {
isHeading: false,
items: ['Performa', '4/5', '5/5', '4/5']
}]
}, {
text: 'Apakah ini membantu menjelaskan perbedaannya?'
}]
})[!TIP] Anda dapat dengan mudah menambahkan penyorotan sintaks dengan mengimpor
tokenizeCodelangsung dari Baileys.
import { tokenizeCode } from 'bailcin'
const language = 'javascript'
const code = 'console.log("Hello, World!")'
sock.sendMessage(jid, {
disclaimerText: 'Contoh tokenisasi Code Block',
richResponse: [{
text: 'Contoh Penggunaan',
}, {
language,
code: tokenizeCode(code, language)
}, {
text: 'Cukup sederhana, bukan?'
}]
})Bahasa yang didukung:
css,html,javascript,typescript,python,golang,rust,c,c#,c++,bash,bat,powershell.
Pesan dengan Code Block
[!NOTE] Fitur ini sudah menyertakan tokenizer bawaan dengan
tokenizeCode.
sock.sendMessage(jid, {
disclaimerText: 'Code Block',
headerText: '## Contoh Penggunaan',
contentText: '---',
code: 'console.log("Hello, World!")',
language: 'javascript',
footerText: 'Cukup sederhana, bukan?'
})Pesan dengan Inline Entities
sock.sendMessage(jid, {
disclaimerText: 'Inline Entities',
headerText: '## Lihat Ini!',
contentText: '---',
links: [{
text: '1. Google',
title: 'Mesin Pencari Populer',
url: 'https://www.google.com/'
}, {
text: '2. YouTube',
title: 'Platform Streaming Populer',
url: 'https://www.youtube.com/'
}, {
text: '3. Modded Baileys',
title: 'Fork Baileys yang Direkomendasikan',
url: 'https://github.com/ndradev/bailcin'
}],
footerText: '---'
})Pesan dengan Table
sock.sendMessage(jid, {
disclaimerText: 'Tabel',
headerText: '## Perbandingan antara Node.js, Bun, dan Deno',
contentText: '---',
title: 'Perbandingan Runtime',
table: [
['', 'Node.js', 'Bun', 'Deno'],
['Engine', 'V8 (C++)', 'JavaScriptCore (C++)', 'V8 (C++)'],
['Performa', '4/5', '5/5', '4/5']
],
noHeading: false, // --- Opsional
footerText: 'Apakah ini membantu menjelaskan perbedaannya?'
})Status Mention
sock.sendMessage([jidA, jidB, jidC], {
text: 'Halo!'
})Mengirim Media
[!NOTE] Untuk pesan media, Anda dapat memberikan
Buffersecara langsung, atau objek dengan{ stream: Readable }atau{ url: string }(path file lokal atau URL HTTP/HTTPS).
Gambar
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'Luar biasa'
}, {
quoted: message
})Video
sock.sendMessage(jid, {
video: {
url: './path/to/video.mp4'
},
gifPlayback: false, // --- true untuk mengirim video sebagai GIF
ptv: false, // --- true untuk mengirim video sebagai PTV
caption: 'Luar biasa'
}, {
quoted: message
})Stiker
sock.sendMessage(jid, {
sticker: {
url: './path/to/sticker.webp'
}
}, {
quoted: message
})Audio
sock.sendMessage(jid, {
audio: {
url: './path/to/audio.mp3'
},
ptt: false // --- true untuk mengirim audio sebagai Voice Note
}, {
quoted: message
})Dokumen
sock.sendMessage(jid, {
document: {
url: './path/to/document.pdf'
},
mimetype: 'application/pdf',
caption: 'Hasil kerja saya!'
}, {
quoted: message
})Album (Gambar & Video)
sock.sendMessage(jid, {
album: [{
image: {
url: './path/to/image.jpg'
},
caption: 'Gambar 1'
}, {
video: {
url: './path/to/video.mp4'
},
caption: 'Video 1'
}, {
image: {
url: './path/to/image.jpg'
},
caption: 'Gambar 2'
}, {
video: {
url: './path/to/video.mp4'
},
caption: 'Video 2'
}]
}, {
quoted: message
})Sticker Pack
[!IMPORTANT] Jika
sharpatau@napi-rs/imagetidak terinstal,coverdanstickersharus sudah dalam format WebP.
sock.sendMessage(jid, {
cover: {
url: './path/to/image.webp'
},
stickers: [{
data: {
url: './path/to/image.webp'
}
}, {
data: {
url: './path/to/image.webp'
}
}, {
data: {
url: './path/to/image.webp'
}
}],
name: 'Sticker Pack Saya',
publisher: 'Lia Wynn',
description: 'bailcin'
}, {
quoted: message
})Mengirim Pesan Interaktif
Buttons
// --- Pesan buttons biasa
sock.sendMessage(jid, {
text: 'Tombol!',
footer: 'bailcin',
buttons: [{
text: 'Daftar',
id: '#SignUp'
}]
}, {
quoted: message
})
// --- Buttons dengan Media & Native Flow
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'Tombol dan Native Flow!',
footer: 'bailcin',
buttons: [{
text: 'Penilaian',
id: '#Rating'
}, {
text: 'Pilih',
sections: [{
title: 'Bagian 1',
rows: [{
header: '',
title: 'Bahan Rahasia',
description: '',
id: '#SecretIngredient'
}]
}, {
title: 'Bagian 2',
highlight_label: 'Populer',
rows: [{
header: '',
title: 'Kupon',
description: '',
id: '#CouponCode'
}]
}]
}]
}, {
quoted: message
})List
[!NOTE] Hanya berfungsi di chat pribadi (
@s.whatsapp.net).
sock.sendMessage(jid, {
text: 'Daftar!',
footer: 'bailcin',
buttonText: 'Pilih',
title: 'Halo',
sections: [{
title: 'Menu 1',
rows: [{
title: 'AI',
description: '',
rowId: '#AI'
}]
}, {
title: 'Menu 2',
rows: [{
title: 'Cari',
description: '',
rowId: '#Search'
}]
}]
}, {
quoted: message
})Interactive
// --- Native Flow
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'Interaktif!',
footer: 'bailcin',
optionText: 'Pilih Opsi', // --- Opsional, bungkus semua native flow ke dalam satu list
optionTitle: 'Pilih Opsi', // --- Opsional
offerText: 'Kupon Terbaru!', // --- Opsional, tambahkan penawaran ke pesan
offerCode: 'bailcin', // --- Opsional
offerUrl: 'https://github.com/ndradev/bailcin', // --- Opsional
offerExpiration: Date.now() + 3_600_000, // --- Opsional
nativeFlow: [{
text: 'Sapaan',
id: '#Greeting',
icon: 'review' // --- Opsional
}, {
text: 'Telepon',
call: '628123456789'
}, {
text: 'Salin',
copy: 'bailcin'
}, {
text: 'Sumber',
url: 'https://github.com/ndradev/bailcin',
useWebview: true // --- Opsional
}, {
text: 'Pilih',
sections: [{
title: 'Bagian 1',
rows: [{
header: '',
title: 'Kupon',
description: '',
id: '#CouponCode'
}]
}, {
title: 'Bagian 2',
highlight_label: 'Populer',
rows: [{
header: '',
title: 'Bahan Rahasia',
description: '',
id: '#SecretIngredient'
}]
}],
icon: 'default' // --- Opsional
}],
interactiveAsTemplate: false, // --- Opsional, bungkus pesan interaktif ke dalam template
}, {
quoted: message
})
// --- Carousel & Native Flow
sock.sendMessage(jid, {
text: 'Interaktif dengan Carousel!',
footer: 'bailcin',
cards: [{
image: {
url: './path/to/image.jpg'
},
caption: 'Gambar 1',
footer: 'Pinterest',
nativeFlow: [{
text: 'Sumber',
url: 'https://github.com/ndradev/bailcin',
useWebview: true
}]
}, {
image: {
url: './path/to/image.jpg'
},
caption: 'Gambar 2',
footer: 'Pinterest',
offerText: 'Kupon Baru!',
offerCode: 'bailcin',
offerUrl: 'https://github.com/ndradev/bailcin',
offerExpiration: Date.now() + 3_600_000,
nativeFlow: [{
text: 'Sumber',
url: 'https://github.com/ndradev/bailcin'
}]
}, {
image: {
url: './path/to/image.jpg'
},
caption: 'Gambar 3',
footer: 'Pinterest',
optionText: 'Pilih Opsi',
optionTitle: 'Pilih Opsi',
offerText: 'Kupon Baru!',
offerCode: 'bailcin',
offerUrl: 'https://github.com/ndradev/bailcin',
offerExpiration: Date.now() + 3_600_000,
nativeFlow: [{
text: 'Produk',
id: '#Product',
icon: 'default'
}, {
text: 'Sumber',
url: 'https://github.com/ndradev/bailcin'
}]
}]
}, {
quoted: message
})
// --- Native Flow dengan Audio di Footer
sock.sendMessage(jid, {
text: 'Musik di footer!',
audioFooter: {
url: './path/to/audio.mp3'
}, // --- Seperti metode upload media lainnya, buffer dan stream didukung
nativeFlow: [{
text: 'Bagus, lanjut',
id: '#Next',
icon: 'review'
}, {
text: 'Lewati',
id: '#Skip',
icon: 'default'
}]
}, {
quoted: message
})Hydrated Template
sock.sendMessage(jid, {
title: 'Halo',
image: {
url: './path/to/image.jpg'
},
caption: 'Template!',
footer: 'bailcin',
templateButtons: [{
text: 'Ketuk di sini',
id: '#Order'
}, {
text: 'Sumber',
url: 'https://github.com/ndradev/bailcin'
}, {
text: 'Telepon',
call: '628123456789'
}]
}, {
quoted: message
})Mengirim Pesan Pembayaran
Invite Payment
sock.sendMessage(jid, {
paymentInviteServiceType: 3 // 1, 2, atau 3
})Invoice
[!NOTE] Pesan Invoice belum didukung.
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
invoiceNote: 'Invoice'
})Order
sock.sendMessage(chat, {
orderText: 'Pesanan',
thumbnail: fs.readFileSync('./path/to/image.jpg') // --- Harus dalam format buffer
}, {
quoted: message
})Request Payment
sock.sendMessage(jid, {
text: 'Request Pembayaran',
requestPaymentFrom: '[email protected]'
})Opsi Pesan Lainnya
AI Icon
[!NOTE] Hanya berfungsi di chat pribadi (
@s.whatsapp.net).
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'Dengan ikon AI!',
ai: true
}, {
quoted: message
})Ephemeral
[!NOTE] Membungkus pesan ke dalam
ephemeralMessage.
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'Ephemeral',
ephemeral: true
})External Ad Reply
[!NOTE] Menambahkan thumbnail iklan ke pesan (mungkin tidak ditampilkan di beberapa versi WhatsApp).
sock.sendMessage(jid, {
text: 'External Ad Reply',
externalAdReply: {
title: 'Tahukah Anda?',
body: 'Saya tidak tahu',
thumbnail: fs.readFileSync('./path/to/image.jpg'), // --- Harus dalam format buffer
largeThumbnail: false, // --- Atau true untuk thumbnail yang lebih besar
url: 'https://github.com/ndradev/bailcin' // --- Opsional, digunakan untuk caching thumbnail internal WhatsApp dan URL langsung
}
}, {
quoted: message
})Group Status
[!NOTE] Hanya berfungsi di chat grup (
@g.us).
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'Status Grup!',
groupStatus: true
})Lottie Sticker
[!NOTE] Membungkus pesan ke dalam
lottieStickerMessage.
sock.sendMessage(jid, {
sticker: {
url: './path/to/sticker.webp'
},
isLottie: true
})Raw
sock.sendMessage(jid, {
extendedTextMessage: {
text: 'Dibangun secara manual menggunakan struktur proto WhatsApp mentah',
contextInfo: {
externalAdReply: {
title: 'bailcin',
thumbnail: fs.readFileSync('./path/to/image.jpg'),
sourceApp: 'whatsapp',
showAdAttribution: true,
mediaType: 1
}
}
},
raw: true
}, {
quoted: message
})Secure Meta Service Label
sock.sendMessage(jid, {
text: 'Hanya sebuah label!',
secureMetaServiceLabel: true
})Spoiler
[!NOTE] Membungkus pesan ke dalam
spoilerMessage.
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'Spoiler',
spoiler: true
})View Once
[!NOTE] Membungkus pesan ke dalam
viewOnceMessage.
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'View Once',
viewOnce: true
})View Once V2
[!NOTE] Membungkus pesan ke dalam
viewOnceMessageV2.
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'View Once V2',
viewOnceV2: true
})View Once V2 Extension
[!NOTE] Membungkus pesan ke dalam
viewOnceMessageV2Extension.
sock.sendMessage(jid, {
image: {
url: './path/to/image.jpg'
},
caption: 'View Once V2 Extension',
viewOnceV2Extension: true
})Modifikasi Pesan
Hapus Pesan
sock.sendMessage(jid, {
delete: message.key
})Edit Pesan
// --- Edit teks biasa
sock.sendMessage(jid, {
text: 'Maksud saya, bagus!',
edit: message.key
})
// --- Edit caption media
sock.sendMessage(jid, {
caption: 'Maksud saya, ini gambarnya!',
edit: message.key
})Konten Tambahan
Cari User ID (JID/PN/LID)
[!NOTE] ID harus berisi angka saja (tanpa +, (), atau -) dan harus menyertakan kode negara dengan format ID WhatsApp.
// --- PN (Phone Number)
const phoneNumber = '[email protected]'
const ids = await sock.findUserId(phoneNumber)
console.log('User ID:', ids)
// --- LID (Local Identifier)
const lid = '43411111111111@lid'
const ids = await sock.findUserId(lid)
console.log('User ID:', ids)
// --- Output
// {
// phoneNumber: '[email protected]',
// lid: '43411111111111@lid'
// }
// --- Output saat gagal
// {
// phoneNumber: '[email protected]',
// lid: undefined
// }
// --- Bentuk output sama terlepas dari tipe inputRequest Custom Pairing Code
[!NOTE] Nomor telepon harus berisi angka saja (tanpa +, (), atau -) dan harus menyertakan kode negara.
const phoneNumber = '6281111111111'
const customPairingCode = 'STARFALL'
await sock.requestPairingCode(phoneNumber, customPairingCode)
console.log('Pairing code:', customPairingCode)Pemrosesan Gambar
[!NOTE] Secara otomatis menggunakan library pemrosesan gambar yang tersedia:
sharp,@napi-rs/image, ataujimp.
import { getImageProcessingLibrary } from 'bailcin'
import { readFile } from 'fs/promises'
const lib = await getImageProcessingLibrary()
const bufferOrFilePath = './path/to/image.jpg'
const width = 512
let output
// --- Jika sharp terinstal
if (lib.sharp?.default) {
const img = lib.sharp.default(bufferOrFilePath)
output = await img.resize(width)
.jpeg({ quality: 80 })
.toBuffer()
}
// --- Jika @napi-rs/image terinstal
else if (lib.image?.Transformer) {
// --- Harus dalam format buffer
const inputBuffer = Buffer.isBuffer(bufferOrFilePath)
? bufferOrFilePath
: await readFile(bufferOrFilePath)
const img = new lib.image.Transformer(inputBuffer)
output = await img.resize(width, undefined, 0)
.jpeg(50)
}
// --- Jika jimp terinstal
else if (lib.jimp?.Jimp) {
const img = await lib.jimp.Jimp.read(bufferOrFilePath)
output = await img
.resize({ w: width, mode: lib.jimp.ResizeStrategy.BILINEAR })
.getBuffer('image/jpeg', { quality: 50 })
}
// --- Fallback
else {
throw new Error('Tidak ada library pemrosesan gambar yang tersedia')
}
console.log('Proses selesai!')
console.dir(output, { depth: null })Manajemen Newsletter
// --- Buat newsletter baru
sock.newsletterCreate('bailcin', 'Pembaruan mingguan')
// --- Ambil informasi
const metadata = sock.newsletterMetadata('1231111111111@newsletter')
console.dir(metadata, { depth: null })
// --- Ambil jumlah subscriber
const subscribers = await sock.newsletterSubscribers('1231111111111@newsletter')
console.dir(subscribers, { depth: null })
// --- Follow dan Unfollow
sock.newsletterFollow('1231111111111@newsletter')
sock.newsletterUnfollow('1231111111111@newsletter')
// --- Mute dan Unmute
sock.newsletterMute('1231111111111@newsletter')
sock.newsletterUnmute('1231111111111@newsletter')
// --- Turunkan admin
sock.newsletterDemote('1231111111111@newsletter', '[email protected]')
// --- Ganti pemilik
sock.newsletterChangeOwner('1231111111111@newsletter', '[email protected]')
// --- Update newsletter
sock.newsletterUpdate('1231111111111@newsletter', { name: 'bailcin' })
// --- Ganti nama
sock.newsletterUpdateName('1231111111111@newsletter', 'bailcin')
// --- Ganti deskripsi
sock.newsletterUpdateDescription('1231111111111@newsletter', 'Pembaruan mingguan')
// --- Ganti foto
sock.newsletterUpdatePicture('1231111111111@newsletter', {
url: 'path/to/image.jpg'
})
// --- Hapus foto
sock.newsletterRemovePicture('1231111111111@newsletter')
// --- Reaksi ke pesan
sock.newsletterReactMessage('1231111111111@newsletter', '100', '👍')
// --- Ambil jumlah admin
const count = await sock.newsletterAdminCount('1231111111111@newsletter')
// --- Ambil semua newsletter yang diikuti
const newsletters = await sock.newsletterSubscribed()
console.dir(newsletters, { depth: null })
// --- Ambil pesan newsletter
const messages = sock.newsletterFetchMessages('jid', '1231111111111@newsletter', 50, 0, 0)
console.dir(messages, { depth: null })
// --- Hapus newsletter
sock.newsletterDelete('1231111111111@newsletter')Manajemen Grup
// --- Buat grup baru dan tambah peserta menggunakan JID mereka
const group = sock.groupCreate('bailcin', ['[email protected]'])
console.dir(group, { depth: null })
// --- Ambil informasi grup
const metadata = await sock.groupMetadata(jid)
console.dir(metadata, { depth: null })
// --- Ambil kode undangan grup
const inviteCode = await sock.groupInviteCode(jid)
console.dir(inviteCode, { depth: null })
// --- Revoke tautan undangan
sock.groupRevokeInvite(jid)
// --- Terima undangan grup
sock.groupAcceptInvite(inviteCode)
// --- Tinggalkan grup
sock.groupLeave(jid)
// --- Tambah peserta
sock.groupParticipantsUpdate(jid, ['[email protected]'], 'add')
// --- Hapus peserta
sock.groupParticipantsUpdate(jid, ['[email protected]'], 'remove')
// --- Promosikan ke admin
sock.groupParticipantsUpdate(jid, ['[email protected]'], 'promote')
// --- Turunkan dari admin
sock.groupParticipantsUpdate(jid, ['[email protected]'], 'demote')
// --- Terima permintaan bergabung
sock.groupRequestParticipantsUpdate(jid, ['[email protected]'], 'approve')
// --- Ganti nama grup
sock.groupUpdateSubject(jid, 'bailcin')
// --- Ganti deskripsi
sock.groupUpdateDescription(jid, 'Deskripsi diperbarui')
// --- Ganti foto
sock.updateProfilePicture(jid, {
url: 'path/to/image.jpg'
})
// --- Hapus foto
sock.removeProfilePicture(jid)
// --- Set grup hanya admin yang bisa chat
sock.groupSettingUpdate(jid, 'announcement')
// --- Set grup semua bisa chat
sock.groupSettingUpdate(jid, 'not_announcement')
// --- Set hanya admin bisa edit info grup
sock.groupSettingUpdate(jid, 'locked')
// --- Set semua peserta bisa edit info grup
sock.groupSettingUpdate(jid, 'unlocked')
// --- Set hanya admin bisa menambah peserta
sock.groupMemberAddMode(jid, 'admin_add')
// --- Set semua peserta bisa menambah peserta
sock.groupMemberAddMode(jid, 'all_member_add')
// --- Aktifkan/nonaktifkan pesan sementara dalam format detik
sock.groupToggleEphemeral(jid, 86400)
// --- Nonaktifkan pesan sementara
sock.groupToggleEphemeral(jid, 0)
// --- Aktifkan/nonaktifkan mode persetujuan keanggotaan
sock.groupJoinApprovalMode(jid, 'on')
sock.groupJoinApprovalMode(jid, 'off')
// --- Ambil metadata semua grup
const groups = await sock.groupFetchAllParticipating()
console.dir(groups, { depth: null })
// --- Ambil permintaan bergabung yang tertunda
const requests = await sock.groupRequestParticipantsList(jid)
console.dir(requests, { depth: null })
// --- Ambil info grup dari tautan
const group = await sock.groupGetInviteInfo('ABC123456789')
console.log('Info grup dari kode undangan:', group)
// --- Update label anggota bot
sock.updateMemberLabel(jid, 'bailcin')Manajemen Komunitas
// --- Buat komunitas baru dan tambah deskripsi
const community = await sock.communityCreate('bailcin', 'Pembaruan mingguan')
console.dir(community, { depth: null })
// --- Buat subgrup untuk komunitas dan tambah peserta menggunakan JID mereka
const group = await sock.communityCreateGroup('Pengumuman', ['[email protected]'], communityJid)
// --- Tautkan grup yang sudah ada
sock.communityLinkGroup(groupJid, communityJid)
// --- Lepas tautan grup
sock.communityUnlinkGroup(groupJid, communityJid)
// --- Ambil info komunitas
const metadata = await sock.communityMetadata(jid)
console.dir(metadata, { depth: null })
// --- Ambil kode undangan komunitas
const inviteCode = await sock.communityInviteCode(jid)
console.dir(inviteCode, { depth: null })
// --- Revoke tautan undangan
sock.communityRevokeInvite(jid)
// --- Terima undangan komunitas
sock.communityAcceptInvite(inviteCode)
// --- Tinggalkan komunitas
sock.communityLeave(jid)
// --- Terima permintaan bergabung
sock.communityRequestParticipantsUpdate(jid, ['[email protected]'], 'approve')
// --- Ganti nama komunitas
sock.communityUpdateSubject(jid, 'bailcin')
// --- Ganti deskripsi
sock.communityUpdateDescription(jid, 'Deskripsi diperbarui')
// --- Set hanya admin yang bisa chat
sock.communitySettingUpdate(jid, 'announcement')
// --- Set semua bisa chat
sock.communitySettingUpdate(jid, 'not_announcement')
// --- Set hanya admin bisa edit info
sock.communitySettingUpdate(jid, 'locked')
// --- Set semua bisa edit info
sock.communitySettingUpdate(jid, 'unlocked')
// --- Set hanya admin bisa menambah peserta
sock.communityMemberAddMode(jid, 'admin_add')
// --- Set semua bisa menambah peserta
sock.communityMemberAddMode(jid, 'all_member_add')
// --- Aktifkan/nonaktifkan pesan sementara
sock.communityToggleEphemeral(jid, 86400)
// --- Nonaktifkan pesan sementara
sock.communityToggleEphemeral(jid, 0)
// --- Aktifkan/nonaktifkan mode persetujuan
sock.communityJoinApprovalMode(jid, 'on')
sock.communityJoinApprovalMode(jid, 'off')
// --- Ambil metadata semua komunitas
const communities = await sock.communityFetchAllParticipating()
console.dir(communities, { depth: null })
// --- Ambil semua grup tertaut komunitas
const linked = await sock.communityFetchLinkedGroups(jid)
console.dir(linked, { depth: null })
// --- Ambil permintaan bergabung yang tertunda
const requests = await sock.communityRequestParticipantsList(jid)
console.dir(requests, { depth: null })
// --- Ambil info komunitas dari tautan
const community = await sock.communityGetInviteInfo('ABC123456789')
console.log('Info komunitas dari kode undangan:', community)Manajemen Profil
// --- Ambil foto profil pengguna
const url = await sock.profilePictureUrl(jid, 'image')
console.log('URL foto profil:', url)
// --- Perbarui foto profil
sock.updateProfilePicture(jid, buffer)
sock.updateProfilePicture(jid, { url })
// --- Hapus foto profil
sock.removeProfilePicture(jid)
// --- Perbarui nama profil
sock.updateProfileName('Nama Saya')
// --- Perbarui status profil
sock.updateProfileStatus('Tersedia')
// --- Presence
sock.sendPresenceUpdate('available', jid)
sock.presenceSubscribe(jid)
// --- Tanda terima baca
sock.readMessages([message.key])
sock.sendReceipt(jid, participant, [messageId], 'read')
// --- Blokir pengguna
sock.updateBlockStatus(jid, 'block')
// --- Buka blokir pengguna
sock.updateBlockStatus(jid, 'unblock')
// --- Ambil daftar blokir
const blocked = await sock.fetchBlocklist()
console.dir(blocked, { depth: null })
// --- Modifikasi chat
sock.chatModify({
archive: true,
lastMessageOrig: message,
lastMessage: message
}, jid)
// --- Star pesan
sock.star(jid, [{ id: messageId, fromMe: true }], true)
// --- Kontak
sock.addOrEditContact(jid, { displayName: 'Starseed' })
sock.removeContact(jid)
// --- Label
sock.addChatLabel(jid, labelId)
sock.removeChatLabel(jid, labelId)
sock.addMessageLabel(jid, messageId, labelId)
// --- Sinkronisasi state aplikasi
sock.resyncAppState(['regular', 'critical_block'], true)
// --- Ambil profil bisnis
const profile = await sock.getBusinessProfile(jid)
console.dir(profile, { depth: null })Manajemen Bisnis
// --- Buat produk baru
const product = await sock.productCreate({
name: 'Starseed (Premium)',
description: 'Dapatkan versi lengkap Starseed!',
price: 100000,
currency: 'IDR',
originCountryCode: 'ID',
images: [
bufferImage,
{
url: './path/to/image.jpg'
}
]
})
console.dir(product, { depth: null })
// --- Perbarui produk
await sock.productUpdate(productId, {
name: 'Starseed (Premium)',
description: 'Dapatkan versi lengkap Starseed dengan fitur lebih banyak!',
price: 75000,
currency: 'IDR',
images: [
{
url: './path/to/image.jpg'
}
]
})
// --- Hapus produk
sock.productDelete([productId])
// --- Ambil info katalog
const { products, nextPageCursor } = await sock.getCatalog({
jid: '[email protected]',
limit: 10
})
// --- Ambil koleksi
const collections = await sock.getCollections('[email protected]', 10)
console.dir(collections, { depth: null })
// --- Ambil info pesanan
const order = await sock.getOrderDetails(orderId, tokenBase64)
console.dir(order, { depth: null })
// --- Perbarui profil bisnis
await sock.updateBusinessProfile({
address: 'Jakarta, Indonesia',
description: 'Toko Resmi Starseed',
websites: ['https://github.com/ndradev/bailcin'],
email: '[email protected]',
hours: {
timezone: 'Asia/Jakarta',
days: [{ day: 'mon', mode: 'open_24h' }]
}
})
// --- Perbarui sampul
sock.updateCoverPhoto({
url: './path/to/image.jpg'
})
// --- Hapus sampul
sock.removeCoverPhoto(coverId)
// --- Perbarui balasan cepat
sock.addOrEditQuickReply({
shortcut: 'hello',
message: 'Halo dari akun bisnis',
})
// --- Hapus balasan cepat
sock.removeQuickReply(timestamp)Manajemen Privasi
// --- Perbarui privasi terakhir dilihat
sock.updateLastSeenPrivacy('all')
sock.updateLastSeenPrivacy('contacts')
sock.updateLastSeenPrivacy('contact_blacklist')
sock.updateLastSeenPrivacy('nobody')
// --- Perbarui privasi online
sock.updateOnlinePrivacy('all')
sock.updateOnlinePrivacy('match_last_seen')
// --- Perbarui privasi foto profil
sock.updateProfilePicturePrivacy('contacts')
// --- Perbarui privasi status
sock.updateStatusPrivacy('contacts')
// --- Perbarui privasi tanda terima baca
sock.updateReadReceiptsPrivacy('all')
sock.updateReadReceiptsPrivacy('none')
// --- Perbarui privasi menambah grup
sock.updateGroupsAddPrivacy('all')
sock.updateGroupsAddPrivacy('contacts')
// --- Perbarui privasi pesan
sock.updateMessagesPrivacy('all')
sock.updateMessagesPrivacy('contacts')
sock.updateMessagesPrivacy('nobody')
// --- Perbarui privasi panggilan
sock.updateCallPrivacy('everyone')
// --- Perbarui mode pesan sementara default
sock.updateDefaultDisappearingMode(86400)
// --- Perbarui privasi pratinjau tautan
sock.updateDisableLinkPreviewsPrivacy(true)Events
sock.ev.on('connection.update', (update) => {})
sock.ev.on('creds.update', (update) => {})
sock.ev.on('messaging-history.set', (update) => {})
sock.ev.on('messaging-history.status', (update) => {})
sock.ev.on('chats.upsert', (update) => {})
sock.ev.on('chats.update', (update) => {})
sock.ev.on('chats.delete', (update) => {})
sock.ev.on('chats.lock', (update) => {})
sock.ev.on('lid-mapping.update', (update) => {})
sock.ev.on('presence.update', (update) => {})
sock.ev.on('contacts.upsert', (update) => {})
sock.ev.on('contacts.update', (update) => {})
sock.ev.on('messages.delete', (update) => {})
sock.ev.on('messages.update', (update) => {})
sock.ev.on('messages.media-update', (update) => {})
sock.ev.on('messages.upsert', (update) => {})
sock.ev.on('messages.reaction', (update) => {})
sock.ev.on('message-receipt.update', (update) => {})
sock.ev.on('groups.upsert', (update) => {})
sock.ev.on('groups.update', (update) => {})
sock.ev.on('group-participants.update', (update) => {})
sock.ev.on('group.join-request', (update) => {})
sock.ev.on('group.member-tag.update', (update) => {})
sock.ev.on('blocklist.set', (update) => {})
sock.ev.on('blocklist.update', (update) => {})
sock.ev.on('call', (update) => {})
sock.ev.on('labels.edit', (update) => {})
sock.ev.on('labels.association', (update) => {})
sock.ev.on('newsletter.reaction', (update) => {})
sock.ev.on('newsletter.view', (update) => {})
sock.ev.on('newsletter-participants.update', (update) => {})
sock.ev.on('newsletter-settings.update', (update) => {})
sock.ev.on('settings.update', (update) => {})Fork Base
Fork ini didasarkan pada Baileys (GitHub)
Kredit
Fork ini menggunakan definisi Protocol Buffer yang dikelola oleh WPP Connect melalui wa-proto
Kredit sepenuhnya diberikan kepada maintainer asli dan kontributor Baileys:
