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

@tamago19/tamaaago

v2.2.9

Published

WhatsApp API Modification By Tamaaago

Readme

Tama-Baileys

Tentang Tama-Baileys

Tama-Baileys (@tamago19/tamaaago) adalah library open source berbasis WebSocket yang dirancang untuk membuat bot dan sistem otomasi WhatsApp. Berbeda dengan library lain yang memerlukan browser, Tama-Baileys terhubung langsung ke WhatsApp melalui protokol WebSocket sehingga lebih ringan dan efisien.

Library ini merupakan modifikasi dari WhiskeySockets/Baileys dengan penambahan fitur interaktif dan perbaikan khusus untuk kebutuhan bot Indonesia.


Install

via npm (direkomendasikan)

npm install @tamago19/tamaaago

Atau tambahkan ke package.json:

{
  "dependencies": {
    "@tamago19/tamaaago": "^2.2.5"
  }
}

Prerequisites / Peer Dependencies

Beberapa dependency bersifat opsional. Install sesuai kebutuhan:

# Core (wajib):
npm install pino ws

# Untuk fitur media / gambar:
npm install jimp sharp

# Untuk audio:
npm install audio-decode

# Untuk link preview:
npm install link-preview-js

Info Rilis

| Versi | Tanggal | Perubahan | |-------|---------|----------| | 2.2.1 | terbaru | Penambahan fungsi sendButtons untuk pesan interaktif | | 2.2.0 | sebelumnya | Upgrade ke Baileys 7.0.0-rc14, migrasi ESM | | 2.1.x | sebelumnya | Perbaikan pairing dan koneksi |


Fitur Utama

| Fitur | Keterangan | |-------|-----------| | Pesan Interaktif | Tombol, menu dropdown, native flow, CTA (URL, copy, call) | | Album Message | Kirim beberapa gambar sekaligus | | Pesan Event | Undangan acara dengan lokasi dan link join | | Poll Result | Tampilkan hasil voting | | Produk/Katalog | Kirim katalog produk WhatsApp Business | | Request Payment | Invoice dan tagihan pembayaran | | Dokumen Interaktif | PDF/Excel dengan tombol aksi | | Multi-Device | Mendukung MD dan Legacy | | Pairing Kustom | Login via kode pairing (tanpa QR) | | Manajemen Sesi | Sesi tersimpan otomatis (useMultiFileAuthState) |


Dokumentasi Lengkap

Struktur Dasar Project

// bot.js
import { makeWASocket, useMultiFileAuthState, DisconnectReason } from '@tamago19/tamaaago';
import pino from 'pino';

async function start() {
  // Simpan sesi ke folder 'session/'
  const { state, saveCreds } = await useMultiFileAuthState('session');

  const sock = makeWASocket({
    auth: state,
    printQRInTerminal: true,
    logger: pino({ level: 'silent' }),
    syncFullHistory: false,
  });

  sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
    if (connection === 'open') {
      console.log('Berhasil terhubung ke WhatsApp!');
    }
    if (connection === 'close') {
      const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut;
      if (shouldReconnect) start();
    }
  });

  // Simpan kredensial setiap berubah
  sock.ev.on('creds.update', saveCreds);

  // Tangkap pesan masuk
  sock.ev.on('messages.upsert', async ({ messages }) => {
    for (const msg of messages) {
      if (!msg.message) continue;

      const from = msg.key.remoteJid;
      const text = msg.message.conversation
        || msg.message.extendedTextMessage?.text
        || '';

      console.log(`Dari: ${from} | Pesan: ${text}`);

      // Balas pesan
      if (text === 'ping') {
        await sock.sendMessage(from, { text: 'pong!' });
      }
    }
  });
}

start();

Struktur Pesan (Message Object)

Setiap pesan yang masuk memiliki struktur seperti ini:

{
  key: {
    remoteJid: '[email protected]',  // Chat ID pengirim
    fromMe: false,                               // Apakah dari nomor sendiri
    id: 'ABC123XYZ',                             // Unique message ID
    participant: '[email protected]',  // Pengirim (untuk grup)
  },
  messageTimestamp: 1712345678,                  // Timestamp Unix
  pushName: 'Nama Pengguna',                     // Nama yang tersimpan di WA
  message: {
    conversation: 'halo'                          // Isi pesan
  },
  // Atau tipe lain:
  // message: { imageMessage: { ... } }
  // message: { extendedTextMessage: { text: '...' } }
  // message: { videoMessage: { ... } }
  // message: { documentMessage: { ... } }
  // message: { audioMessage: { ... } }
  // message: { stickerMessage: { ... } }
}

Cara Mendapatkan Isi Pesan

// Teks biasa
const text = msg.message.conversation
  || msg.message.extendedTextMessage?.text
  || '';

// Gambar / Media
const image = msg.message.imageMessage;
const caption = image?.caption;
const mediaBuffer = await sock.downloadMediaMessage(msg);

// Video
const video = msg.message.videoMessage;

// Document
const doc = msg.message.documentMessage;
const fileName = doc?.fileName;
const mimeType = doc?.mimetype;

// Audio
const audio = msg.message.audioMessage;

// Sticker
const sticker = msg.message.stickerMessage;

// Quoted Message (pesan yang di-reply)
const quoted = msg.message.extendedTextMessage?.contextInfo?.quotedMessage;

Referensi Pengiriman Pesan

1. Pesan Teks Biasa

await sock.sendMessage(jid, { text: 'Halo dunia!' });

2. Pesan dengan Reply / Quoted

await sock.sendMessage(jid, { text: 'Ini adalah reply' }, { quoted: msg });

3. Pesan Album (Kirim Banyak Gambar)

Kirim beberapa gambar sekaligus dalam satu pesan album:

import fs from 'fs';

await sock.sendMessage(jid, {
    albumMessage: [
        {
            image: fs.readFileSync('./gambar1.jpg'),
            caption: 'Foto pertama'
        },
        {
            image: { url: 'https://example.com/foto.jpg' },
            caption: 'Foto dari URL'
        }
    ]
}, { quoted: msg });

Parameter:

  • image: bisa Buffer, URL string, atau path string
  • caption: teks di bawah gambar

4. Pesan Event / Undangan Acara

Kirim undangan event dengan detail lengkap:

await sock.sendMessage(jid, {
    eventMessage: {
        name: "Webinar Gratis - Belajar Coding",
        description: "Workshop gratis untuk pemula. Belajar JavaScript dari nol!",
        location: {
            degreesLatitude: -7.9666,
            degreesLongitude: 112.6326,
            name: "Online via Zoom"
        },
        joinLink: "https://zoom.us/j/123456789",
        startTime: "1763019000",
        endTime: "1763026200",
        isCanceled: false,
        extraGuestsAllowed: true
    }
}, { quoted: msg });

Parameter:

  • name: judul event
  • description: deskripsi event
  • location: lokasi event (koordinat + nama tempat)
  • joinLink: link untuk join (Zoom, Google Meet, dll)
  • startTime / endTime: waktu dalam format Unix timestamp
  • isCanceled: apakah event dibatalkan
  • extraGuestsAllowed: apakah boleh menambahkan tamu tambahan

5. Pesan Interaktif dengan Tombol (sendButtons)

Ini adalah cara termudah untuk mengirim pesan dengan tombol interaktif. Tombol akan muncul di bawah pesan dan bisa diklik langsung oleh pengguna.

Tombol Quick Reply (paling umum)

import { sendButtons } from '@tamago19/tamaaago';

await sendButtons(sock, jid, {
    text: 'Silakan pilih menu di bawah:',
    footer: 'Bot by Tamaaago',
    buttons: [
        { id: 'menu_info', text: 'Informasi' },
        { id: 'menu_help', text: 'Bantuan' },
        { id: 'menu_contact', text: 'Hubungi Kami' }
    ]
});

Ketika pengguna mengklik tombol, bot akan menerima pesan dengan msg.message.buttonsResponseMessage?.selectedButtonId berisi ID tombol.

Tombol dengan URL (CTA URL)

await sendButtons(sock, jid, {
    text: 'Selamat datang di toko kami!',
    footer: 'Klik tombol untuk aksi',
    buttons: [
        { id: 'opt1', text: 'Lihat Produk' },
        { name: 'cta_url', buttonParamsJson: JSON.stringify({
            display_text: 'Kunjungi Website',
            url: 'https://tokokami.com'
        }) }
    ]
});

Tombol dengan Copy Code

await sendButtons(sock, jid, {
    text: 'Berikut kode promo eksklusif Anda:',
    footer: 'Tekan tombol untuk menyalin kode',
    buttons: [
        { name: 'cta_copy', buttonParamsJson: JSON.stringify({
            display_text: 'Salin Kode',
            id: 'promo_123',
            copy_code: 'HEMAT50'
        }) }
    ]
});

Tombol dengan CTA Call (Telepon)

await sendButtons(sock, jid, {
    text: 'Ada pertanyaan? Hubungi CS kami langsung.',
    footer: 'Layanan 24 jam',
    buttons: [
        { name: 'cta_call', buttonParamsJson: JSON.stringify({
            display_text: 'Telepon Sekarang',
            phone_number: '628123456789'
        }) }
    ]
});

Menangani Respon Tombol

sock.ev.on('messages.upsert', async ({ messages }) => {
    for (const msg of messages) {
        // Cek apakah ini response dari tombol
        const buttonResponse = msg.message?.buttonsResponseMessage;
        if (buttonResponse) {
            const selectedId = buttonResponse.selectedButtonId;
            const selectedDisplay = buttonResponse.displayText;

            console.log(`Tombol diklik: ${selectedId}`);

            if (selectedId === 'menu_info') {
                await sock.sendMessage(msg.key.remoteJid, {
                    text: 'Berikut informasi lengkap...'
                });
            } else if (selectedId === 'menu_help') {
                await sock.sendMessage(msg.key.remoteJid, {
                    text: 'Ketik !help untuk bantuan.'
                });
            }
            continue;
        }
    }
});

6. Pesan Interaktif dengan Menu Dropdown (Single Select)

Menu dropdown memungkinkan pengguna memilih dari daftar opsi:

await sock.sendMessage(jid, {
    interactiveMessage: {
        header: {
            title: "Menu Utama",
            hasMediaAttachment: false
        },
        body: {
            text: "Pilih layanan yang Anda butuhkan:"
        },
        footer: {
            text: "© Tama-Baileys Bot"
        },
        nativeFlowMessage: {
            messageParamsJson: JSON.stringify({
                single_select: {
                    title: "Daftar Menu",
                    list_title: "Pilih Opsi",
                    button_title: "Tampilkan Menu"
                }
            }),
            buttons: [
                {
                    name: "single_select",
                    buttonParamsJson: JSON.stringify({
                        title: "Menu Utama",
                        sections: [
                            {
                                title: "Layanan",
                                highlight_label: "Populer",
                                rows: [
                                    {
                                        header: "Customer Service",
                                        title: "Hubungi Tim Kami",
                                        description: "Chat langsung dengan CS kami",
                                        id: "cs_chat"
                                    },
                                    {
                                        header: "Produk",
                                        title: "Lihat Katalog",
                                        description: "Lihat semua produk kami",
                                        id: "product_catalog"
                                    },
                                    {
                                        header: "Promo",
                                        title: "Kode Promo",
                                        description: "Dapatkan diskon eksklusif",
                                        id: "promo_codes"
                                    }
                                ]
                            },
                            {
                                title: "Lainnya",
                                rows: [
                                    {
                                        title: "Tentang Kami",
                                        description: "Kenali lebih dekat",
                                        id: "about_us"
                                    },
                                    {
                                        title: "Cara Pemesanan",
                                        description: "Panduan lengkap",
                                        id: "how_to_order"
                                    }
                                ]
                            }
                        ]
                    })
                }
            ]
        }
    }
}, { quoted: msg });

Parameter single_select:

  • sections: array bagian menu
    • title: nama bagian
    • highlight_label: label khusus (misal "Populer")
    • rows: item dalam bagian
      • header / title: teks opsi
      • description: teks penjelasan
      • id: ID yang dikirim saat dipilih

7. Pesan Produk / Katalog WhatsApp Business

Kirim pesan katalog produk:

await sock.sendMessage(jid, {
    productMessage: {
        product: {
            productImage: { url: 'https://example.com/phone.jpg' },
            productId: 'PHONE001',
            title: "Smartphone XYZ Pro",
            description: "RAM 8GB, Storage 256GB, Kamera 108MP",
            retailerId: 'STORE001',
            url: 'https://tokokami.com/phone-xyz-pro',
            currencyCode: "IDR",
            price_amount_1000: 4500000,
            productSections: [
                {
                    title: "Spesifikasi",
                    rows: [
                        { title: "Layar", description: "6.7 inch AMOLED" },
                        { title: "Baterai", description: "5000mAh" },
                        { title: "Prosesor", description: "Snapdragon 888" }
                    ]
                }
            ]
        },
        businessOwnerJid: '[email protected]',
        footer: 'Gratis ongkir seluruh Indonesia!'
    }
});

8. Pesan Polling / Voting

Kirim Poll (Buat Voting)

await sock.sendMessage(jid, {
    pollCreationMessage: {
        name: "Pilih Menu Makan Siang",
        options: [
            { optionName: "Nasi Goreng" },
            { optionName: "Mie Ayam" },
            { optionName: "Soto Ayam" },
            { optionName: "Rawon" }
        ],
        selectableOptionsCount: 1
    }
});

Tampilkan Hasil Poll

await sock.sendMessage(jid, {
    pollResultMessage: {
        name: "Pilih Menu Makan Siang",
        pollVotes: [
            { optionName: "Nasi Goreng", optionVoteCount: "12" },
            { optionName: "Mie Ayam", optionVoteCount: "8" },
            { optionName: "Soto Ayam", optionVoteCount: "5" },
            { optionName: "Rawon", optionVoteCount: "3" }
        ]
    }
}, { quoted: msg });

9. Pesan dengan File Dokumen

Kirim dokumen (PDF, Excel, Word, dll) dengan tombol aksi:

import fs from 'fs';

await sock.sendMessage(jid, {
    documentMessage: {
        url: 'https://example.com/laporan.pdf',
        mimetype: 'application/pdf',
        title: 'Laporan Bulanan',
        fileLength: '850000',
        pageCount: 12
    },
    caption: 'Berikut laporan bulanan Anda. Silakan diunduh.',
    footer: 'Finance Department',
    buttons: [
        { id: 'download_report', text: 'Download' },
        { name: 'cta_url', buttonParamsJson: JSON.stringify({
            display_text: 'Simpan ke Cloud',
            url: 'https://drive.example.com/laporan'
        }) }
    ],
    headerType: 1
}, { quoted: msg });

Catatan: File dokumen hanya bisa dikirim dari Buffer (baca dari sistem file):

const pdfBuffer = fs.readFileSync('./laporan.pdf');
const thumbnail = fs.readFileSync('./thumbnail.jpg');

await sock.sendMessage(jid, {
    interactiveMessage: {
        header: { title: 'Laporan Bulanan' },
        body: { text: 'Klik tombol di bawah untuk mengunduh.' },
        footer: { text: 'Finance Dept' },
        nativeFlowMessage: {
            buttons: [
                {
                    name: 'cta_url',
                    buttonParamsJson: JSON.stringify({
                        display_text: 'Download PDF',
                        url: 'https://example.com/laporan.pdf'
                    })
                }
            ]
        }
    }
}, { quoted: msg });

10. Request Pembayaran (Invoice)

Kirim invoice atau tagihan:

await sock.sendMessage(jid, {
    requestPaymentMessage: {
        currency: "IDR",
        amount: 1500000,
        requestFrom: '[email protected]',
        noteMessage: {
            currency: "IDR",
            amount1000: 1500000,
            displayText: "Pembayaran Order #12345"
        },
        expiryTimestamp: Math.floor(Date.now() / 1000) + 86400 * 7 // 7 hari
    }
}, { quoted: msg });

Fitur Tambahan

Broadcast ke Banyak Nomor

const targets = [
    '[email protected]',
    '[email protected]',
    '[email protected]'
];

for (const target of targets) {
    try {
        await sock.sendMessage(target, {
            text: '📢 Pesan broadcast dari Bot!'
        });
        console.log(`Sent to ${target}`);
    } catch (e) {
        console.error(`Failed to send to ${target}:`, e);
    }
}

Kirim dengan Delay (Anti-Spam)

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const targets = ['[email protected]', '[email protected]'];

for (const target of targets) {
    await sock.sendMessage(target, { text: 'Pesan Anda' });
    await delay(3000); // Jeda 3 detik antar pesan
}

Download Media dari Pesan

async function downloadMedia(msg) {
    const buffer = await sock.downloadMediaMessage(msg);
    return buffer;
}

// Atau simpan ke file
import fs from 'fs';

const media = await sock.downloadMediaMessage(msg);
fs.writeFileSync('./downloaded_image.jpg', media);

Handle Button Response (Generic)

sock.ev.on('messages.upsert', async ({ messages }) => {
    for (const msg of messages) {
        // 1. Tombol biasa (buttonsResponseMessage)
        if (msg.message?.buttonsResponseMessage) {
            const { selectedButtonId, displayText } = msg.message.buttonsResponseMessage;
            await sock.sendMessage(msg.key.remoteJid, {
                text: `Anda memilih: ${displayText} (ID: ${selectedButtonId})`
            });
        }

        // 2. List Response (single_select)
        if (msg.message?.listResponseMessage) {
            const { title, description, listItemId } = msg.message.listResponseMessage;
            await sock.sendMessage(msg.key.remoteJid, {
                text: `Anda memilih: ${title}\nID: ${listItemId}`
            });
        }

        // 3. Template Button Reply
        if (msg.message?.templateButtonReplyMessage) {
            const { selectedId } = msg.message.templateButtonReplyMessage;
            await sock.sendMessage(msg.key.remoteJid, {
                text: `Button ID: ${selectedId}`
            });
        }
    }
});

Referensi API Singkat

Import Utama

import {
    makeWASocket,           // Membuat socket/koneksi
    useMultiFileAuthState,  // Simpan sesi ke file
    DisconnectReason,        // Kode disconnect
    sendButtons,            // Kirim pesan tombol interaktif
    sendInteractiveMessage,  // Kirim pesan interaktif level lanjut
    // Tipe data:
    proto,                  // WAProto (semua tipe pesan WA)
    downloadMediaMessage,    // Download media dari pesan
    generateMessageID,      // Generate message ID
    delay,                  // Utility delay
} from '@tamago19/tamaaago';

sock.sendMessage(jid, content, options)

| Parameter | Tipe | Keterangan | |-----------|------|-----------| | jid | string | Chat ID (contoh: [email protected]) | | content | object | Isi pesan | | options | object | Opsi tambahan |

Opsi Umum

{
    quoted: msg,              // Reply ke pesan tertentu
    mentions: ['jid1', 'jid2'], // Mention user
    ephemeralExpiration: 604800, // Pesan hilang (detik)
}

Struktur Project Sederhana

my-whatsapp-bot/
├── package.json
├── bot.js              # Main bot file
├── session/            # Otomatis dibuat, simpan sesi
│   ├── creds.json
│   └── keys/
├── media/              # Folder untuk media
│   └── thumbnails/
└── node_modules/
    └── @tamago19/tamaaago

Catatan Penting

Format JID (Chat ID)

Pairing Code Login (Tanpa QR)

// Kirim kode pairing ke nomor sendiri
const code = await sock.requestPairingCode('628123456789');
console.log('Kode pairing:', code);

Debugging / Logging

const sock = makeWASocket({
    auth: state,
    logger: pino({ level: 'debug' }), // Tampilkan semua log
    printQRInTerminal: true,
});

Kenapa Tama-Baileys?

| | Tama-Baileys | Baileys Original | |--|--|--| | Tombol Interaktif | ✅ Built-in sendButtons | ⚠️ Butuh helper tambahan | | ESM Native | ✅ Full ESM support | ⚠️ Butuh konfigurasi | | Dokumentasi | ✅ Bahasa Indonesia + English | ⚠️ English only | | Update Interaktif | ✅ Langsung integrate | ⚠️ Manual |


Dukungan

  • 📖 Dokumentasi ini
  • 🐛 Laporkan bug via GitHub Issues
  • 💬 Diskusi di repository

Terima kasih telah menggunakan Tama-Baileys! 🚀