@teamolduser/baileys
v9.4.4
Published
A WebSockets library for interacting with WhatsApp Web
Readme
anya-bail — A heavily extended fork of WhiskeySockets/Baileys, the WhatsApp Web API library.
Maintained for @queenanya/baileys | Last updated: April 2026
What's Different from Upstream
| Feature | Upstream Baileys | anya-bail |
| ------------------------------------- | ---------------- | ----------------------------------------- |
| Interactive / button messages | ❌ | ✅ Full support |
| Template messages | ❌ | ✅ |
| List messages | ❌ | ✅ |
| Cards / Carousel messages | ❌ | ✅ |
| Album messages | ❌ | ✅ |
| Sticker pack messages | ❌ | ✅ |
| Share / Request phone number | ❌ | ✅ |
| AI icon on messages | ❌ | ✅ |
| Rich response / Meta AI messages | ❌ | ✅ |
| Outgoing call API | ❌ | ✅ |
| Full MEX notification dispatcher | Partial | ✅ |
| messaging-history.status event | ❌ | ✅ |
| message-capping.update event | ❌ | ✅ |
| Reachout timelock event | ❌ | ✅ |
| MongoDB auth state | ❌ | ✅ |
| Single-file auth state | ❌ | ✅ |
| iOS / Android / KaiOS browser support | Limited | ✅ Extended |
| Pairing race-condition fix | ❌ | ✅ |
| Username in contacts / groups | ❌ | ✅ |
| authorUsername in group events | ❌ | ✅ |
| chunkOrder in history sync | ❌ | ✅ |
| tctoken prune on reconnect | ❌ | ✅ |
| App state sync resilience | Partial | ✅ forceSnapshot + blockedCollections |
| Message ID prefix | 3EB0 | 4NY4W3B |
| Addons layer | ❌ | ✅ 18 addon files |
Installation
npm install anya-bail
# or
yarn add anya-bailTable of Contents
Connecting
import makeWASocket, { DisconnectReason, useMultiFileAuthState } from 'anya-bail'
import { Boom } from '@hapi/boom'
const { state, saveCreds } = await useMultiFileAuthState('./auth_info')
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
})
sock.ev.on('creds.update', saveCreds)
sock.ev.on('connection.update', update => {
const { connection, lastDisconnect } = update
if (connection === 'close') {
const shouldReconnect = (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
if (shouldReconnect) connectToWhatsApp()
}
})Pairing Code (instead of QR):
const code = await sock.requestPairingCode('+91XXXXXXXXXX')
console.log('Pairing code:', code)Sending Messages
Text Message
await sock.sendMessage(jid, { text: 'Hello World!' })Image / Video / Audio / Document
// Image
await sock.sendMessage(jid, { image: { url: './image.jpg' }, caption: 'caption' })
// Video
await sock.sendMessage(jid, { video: { url: './video.mp4' }, caption: 'caption' })
// Audio (PTT)
await sock.sendMessage(jid, { audio: { url: './audio.mp3' }, mimetype: 'audio/mp4', ptt: true })
// Document
await sock.sendMessage(jid, { document: { url: './file.pdf' }, mimetype: 'application/pdf', fileName: 'file.pdf' })Button Message
await sock.sendMessage(jid, {
buttons: [
{ buttonId: 'btn1', buttonText: { displayText: 'Option 1' }, type: 1 },
{ buttonId: 'btn2', buttonText: { displayText: 'Option 2' }, type: 1 }
],
text: 'Pick an option:',
footer: 'Powered by anya-bail'
})Template Message
await sock.sendMessage(jid, {
templateButtons: [
{ index: 1, urlButton: { displayText: 'Visit', url: 'https://example.com' } },
{ index: 2, callButton: { displayText: 'Call', phoneNumber: '+91XXXXXXXXXX' } },
{ index: 3, quickReplyButton: { displayText: 'Reply', id: 'id1' } }
],
text: 'Template body',
footer: 'footer'
})Interactive / List Message
// Interactive buttons
await sock.sendMessage(jid, {
interactiveButtons: [
{ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Yes', id: 'yes' }) },
{ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'No', id: 'no' }) }
],
body: { text: 'Are you sure?' },
footer: { text: 'anya-bail' }
})
// List message
await sock.sendMessage(jid, {
sections: [
{
title: 'Section 1',
rows: [
{ title: 'Row 1', rowId: 'r1', description: 'Description 1' },
{ title: 'Row 2', rowId: 'r2', description: 'Description 2' }
]
}
],
title: 'List Title',
text: 'List body',
footer: 'footer',
buttonText: 'Open List'
})Album Message
await sock.sendMessage(jid, {
album: {
expectedImageCount: 2,
expectedVideoCount: 1
}
})
// Then send each media with albumParentKey
await sock.sendMessage(jid, {
image: { url: './photo1.jpg' },
caption: 'First',
albumParentKey: albumMsg.key
})Sticker Pack Message
await sock.sendMessage(jid, {
stickerPack: {
stickers: [
{
fileSha256: Buffer.from('...'),
fileEncSha256: Buffer.from('...'),
mediaKey: Buffer.from('...'),
directPath: '/v/...',
fileLength: 12345
}
]
}
})Share Phone Number Message
await sock.sendMessage(jid, { sharePhoneNumber: true })Request Phone Number Message
await sock.sendMessage(jid, { requestPhoneNumber: true })AI Icon Feature
// Adds Meta AI bot icon to any message
await sock.sendMessage(jid, { text: 'I am a bot!' }, { ai: true })Rich Response Message
sendTable
await sock.sendTable(
jid,
'Results',
['Name', 'Score'],
[
['Alice', '98'],
['Bob', '87']
],
quotedMsg,
{ headerText: 'Leaderboard:', footer: 'Updated now' }
)sendList
await sock.sendList(jid, 'Todo', ['Buy milk', 'Call mom', 'Push code'], quotedMsg)sendCodeBlock
await sock.sendCodeBlock(jid, `const greet = name => \`Hello \${name}\``, quotedMsg, {
title: 'Example',
language: 'javascript'
})
// Supported: javascript, typescript, python (js, ts, py)sendLatex
await sock.sendLatex(jid, quotedMsg, {
text: 'Quadratic formula:',
expressions: [{ latexExpression: 'x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}' }]
})sendLatexImage
await sock.sendLatexImage(
jid,
quotedMsg,
{ expressions: [{ latexExpression: 'e^{i\\pi}+1=0' }] },
async latex => renderToPng(latex), // → { buffer, width, height }
async (buf, type) => uploadToWA(buf, type) // → { url?, directPath? }
)sendLatexInlineImage
Same as sendLatexImage but each expression renders as its own inline image block.
sendRichMessage
import { RichSubMessageType } from 'anya-bail'
await sock.sendRichMessage(
jid,
[
{ messageType: RichSubMessageType.TEXT, messageText: 'Hello from bot!' },
{
messageType: RichSubMessageType.TABLE,
tableMetadata: {
title: 'Data',
rows: [{ items: ['Key', 'Value'], isHeading: true }, { items: ['status', 'ok'] }]
}
}
],
quotedMsg
)captureUnifiedResponse / sendUnifiedResponse
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
const captured = sock.captureUnifiedResponse(msg.message)
if (captured) {
await sock.sendUnifiedResponse(otherJid, quotedMsg, captured)
}
}
})Calls
// Outgoing call
const { callId } = await sock.initiateCall(jid, { isVideo: false })
await sock.acceptCall(jid, callId)
await sock.preacceptCall(jid, callId)
await sock.muteCall(jid, callId, { isMuted: true })
await sock.terminateCall(jid, callId)
await sock.cancelCall(jid, callId)
// Group call links
const link = await sock.queryCallLink(callLinkToken)
await sock.joinCallLink(callLinkToken)Auth State
// Multi-file (default)
const { state, saveCreds } = await useMultiFileAuthState('./auth_info')
// Single-file
import { useSingleFileAuthState } from 'anya-bail'
const { state, saveState } = useSingleFileAuthState('./auth.json')
// MongoDB
import { useMongoFileAuthState } from 'anya-bail'
const { state, saveCreds } = await useMongoFileAuthState(mongoCollection)MEX Notifications
// Newsletter
sock.ev.on('newsletter-settings.update', ({ id, update }) => {})
sock.ev.on('newsletter-participants.update', ({ id, user, new_role }) => {})
// Linked profiles (LID ↔ PN mapping)
sock.ev.on('lid-mapping.update', ({ lid, pn }) => {})
// Message capping quota
sock.ev.on('message-capping.update', ({ used_quota, total_quota }) => {})
// WA Business reachout timelock
sock.ev.on('connection.update', ({ reachoutTimeLock }) => {
if (reachoutTimeLock?.isActive) {
console.log('Restricted until:', reachoutTimeLock.timeEnforcementEnds)
}
})
// History sync completion / stall
sock.ev.on('messaging-history.status', ({ syncType, status, explicit }) => {
console.log(`History sync ${status} (${syncType}) explicit=${explicit}`)
})Addons
import { buildVCard, AutoReplyEngine, createScheduler, ... } from 'anya-bail'| Addon | Description |
| --------------------- | ---------------------------------------------------- |
| message-composer | Rich/bot message builders (table, list, code, latex) |
| button-sender | Interactive / native-flow button helpers |
| call-handler | Inbound call handling |
| auto-reply | Rule-based auto-reply engine |
| scheduling | Message queue + scheduled sending |
| anti-delete | Detect and recover deleted messages |
| vcard | Build vCard contact strings |
| message-search | Search messages by type/text/regex |
| status-posting | Broadcast statuses to multiple JIDs |
| jid-plotting | JID resolution + LID/PN mapping helpers |
| templates | Template message variable helpers |
| interactive-message | Interactive message utilities |
| from-messages | Message processing helpers |
| from-messages-recv | Inbound message helpers |
| from-messages-send | Outbound message helpers |
| from-chats | Chat event helpers |
Changelog
v8.0.0 — April 2026 (anya-bail)
Based on: WhiskeySockets/Baileys master (April 2026) + InnovatorsSOFT Baileys additions
Added over upstream:
- Full interactive/button/template/list/cards/carousel message system
- Album messages with
albumParentKeysupport - Sticker pack messages
- Share/Request phone number messages
- AI icon on any message (
options.ai = true) - Rich response / Meta AI messages —
sendTable,sendList,sendCodeBlock,sendLatex,sendLatexImage,sendLatexInlineImage,sendRichMessage,captureUnifiedResponse,sendUnifiedResponse - Full outgoing call API (
initiateCall,acceptCall,preacceptCall,muteCall,terminateCall,cancelCall,queryCallLink,joinCallLink) - Full MEX notification dispatcher — reachout timelock, message capping, linked profiles, newsletter ops
messaging-history.statusevent with pause timeout (120s)message-capping.updateeventauthorUsernamein group participant eventschunkOrderin history sync- MongoDB + single-file auth states
- Extended browser map: iOS, Android, androidCompanion, Linux, KaiOS, ChromeOS
getPlatformDisplayName()utility- Pairing race-condition fix (
sendPairingIQ+ queue) buildPairingQRDatafrom companion-reg-client-utils- tctoken issuance + prune system (daily cleanup on reconnect)
- App state sync resilience:
forceSnapshotCollections,blockedCollections ensureLTHashStateVersion,isMissingKeyError,isAppStateSyncIrrecoverable,MAX_SYNC_ATTEMPTSstoreTcTokensFromHistorySync— saves tctokens from history sync chatsSERVER_ERROR_CODES(463 MissingTcToken, 479 SmaxInvalid)- Username fields in Contact, GroupMetadata, GroupParticipant, WAMessageKey
isJidBot,isJidMetaAI,PSA_WIDexportsonBeforeSessionRefreshin identity change handlerQueryIdd,MexOperations,XWAPathsMexUpdatesin Newsletter types- 18-file addons layer
- Message ID prefix:
4NY4W3B - WA version:
2.3000.1037656372
Based on WhiskeySockets/Baileys and InnovatorsSOFT/Baileys. Not affiliated with WhatsApp or Meta.
