UNPKG

secret-company-ltd

Version:
1,686 lines (1,546 loc) 72.7 kB
# <div align='center'>Welcome Boss.</div> <div align="center"> <img src="https://files.catbox.moe/yg0b6h.jpg" alt="Header Image" width="100%"/> <br/> <!-- Badges --> <p> <img src="https://img.shields.io/npm/dw/%40itsukichan%2Fbaileys?label=npm&color=%23CB3837" alt="NPM Downloads"/> <img src="https://img.shields.io/github/v/release/secretcompany/baileys?include_prereleases&sort=semver" alt="Latest Release"/> <img src="https://img.shields.io/github/languages/code-size/secretcompany/baileys" alt="Code Size"/> <img src="https://img.shields.io/github/license/secretcompany/baileys" alt="License"/> <img src="https://img.shields.io/github/stars/secretcompany/baileys" alt="Stars"/> <img src="https://img.shields.io/github/forks/secretcompany/baileys" alt="Forks"/> </p> </div> ## Example Do check out & run [example.ts](Example/example.ts) to see an example usage of the library. The script covers most common use cases. To run the example script, download or clone the repo and then type the following in a terminal: 1. ``` cd path/to/Baileys ``` 2. ``` yarn ``` 3. ``` yarn example ``` # Index - [Connecting Account](#connecting-account) - [Connect with QR-CODE](#starting-socket-with-qr-code) - [Connect with Pairing Code](#starting-socket-with-pairing-code) - [Receive Full History](#receive-full-history) - [Important Notes About Socket Config](#important-notes-about-socket-config) - [Caching Group Metadata (Recommended)](#caching-group-metadata-recommended) - [Improve Retry System & Decrypt Poll Votes](#improve-retry-system--decrypt-poll-votes) - [Receive Notifications in Whatsapp App](#receive-notifications-in-whatsapp-app) - [Save Auth Info](#saving--restoring-sessions) - [Handling Events](#handling-events) - [Example to Start](#example-to-start) - [Decrypt Poll Votes](#decrypt-poll-votes) - [Summary of Events on First Connection](#summary-of-events-on-first-connection) - [Implementing a Data Store](#implementing-a-data-store) - [Whatsapp IDs Explain](#whatsapp-ids-explain) - [Utility Functions](#utility-functions) - [Sending Messages](#sending-messages) - [Non-Media Messages](#non-media-messages) - [Text Message](#text-message) - [Quote Message](#quote-message-works-with-all-types) - [Mention User](#mention-user-works-with-most-types) - [Forward Messages](#forward-messages) - [Location Message](#location-message) - [Live Location Message](#live-location-message) - [Contact Message](#contact-message) - [Reaction Message](#reaction-message) - [Pin Message](#pin-message) - [Keep Message](#keep-message) - [Poll Message](#poll-message) - [Poll Result Message](#poll-result-message) - [Call Message](#call-message) - [Event Message](#event-message) - [Order Message](#order-message) - [Product Message](#product-message) - [Payment Message](#payment-message) - [Payment Invite Message](#payment-invite-message) - [Admin Invite Message](#invite-admin-message) - [Group Invite Message](#group-invite-message) - [Sticker Pack Message](#sticker-pack-message) - [Share Phone Number Message](#share-phone-number-message) - [Request Phone Number Message](#request-phone-number-message) - [Buttons Reply Message](#buttons-reply-message) - [Buttons Message](#buttons-message) - [Buttons List Message](#buttons-list-message) - [Buttons Product List Message](#buttons-product-list-message) - [Buttons Cards Message](#buttons-cards-message) - [Buttons Template Message](#buttons-template-message) - [Buttons Interactive Message](#buttons-interactive-message) - [Buttons Interactive Message PIX](#buttons-interactive-message-pix) - [Buttons Interactive Message PAY](#buttons-interactive-message-PAY) - [Status Mentions Message](#status-mentions-message) - [Send Album Message](#send-album-message) - [Shop Message](#shop-message) - [Collection Message](#collection-message) - [Sending with Link Preview](#sending-messages-with-link-previews) - [Media Messages](#media-messages) - [Gif Message](#gif-message) - [Video Message](#video-message) - [Audio Message](#audio-message) - [Image Message](#image-message) - [Ptv Video Message](#ptv-video-message) - [ViewOnce Message](#view-once-message) - [Modify Messages](#modify-messages) - [Delete Messages (for everyone)](#deleting-messages-for-everyone) - [Edit Messages](#editing-messages) - [Manipulating Media Messages](#manipulating-media-messages) - [Thumbnail in Media Messages](#thumbnail-in-media-messages) - [Downloading Media Messages](#downloading-media-messages) - [Re-upload Media Message to Whatsapp](#re-upload-media-message-to-whatsapp) - [Reject Call](#reject-call) - [Send States in Chat](#send-states-in-chat) - [Reading Messages](#reading-messages) - [Update Presence](#update-presence) - [Modifying Chats](#modifying-chats) - [Archive a Chat](#archive-a-chat) - [Mute/Unmute a Chat](#muteunmute-a-chat) - [Mark a Chat Read/Unread](#mark-a-chat-readunread) - [Delete a Message for Me](#delete-a-message-for-me) - [Delete a Chat](#delete-a-chat) - [Star/Unstar a Message](#starunstar-a-message) - [Disappearing Messages](#disappearing-messages) - [Clear Messages](#clear-messages) - [User Querys](#user-querys) - [Check If ID Exists in Whatsapp](#check-if-id-exists-in-whatsapp) - [Query Chat History (groups too)](#query-chat-history-groups-too) - [Fetch Status](#fetch-status) - [Fetch Profile Picture (groups too)](#fetch-profile-picture-groups-too) - [Fetch Bussines Profile (such as description or category)](#fetch-bussines-profile-such-as-description-or-category) - [Fetch Someone's Presence (if they're typing or online)](#fetch-someones-presence-if-theyre-typing-or-online) - [Change Profile](#change-profile) - [Change Profile Status](#change-profile-status) - [Change Profile Name](#change-profile-name) - [Change Display Picture (groups too)](#change-display-picture-groups-too) - [Remove display picture (groups too)](#remove-display-picture-groups-too) - [Groups](#groups) - [Create a Group](#create-a-group) - [Add/Remove or Demote/Promote](#addremove-or-demotepromote) - [Change Subject (name)](#change-subject-name) - [Change Description](#change-description) - [Change Settings](#change-settings) - [Leave a Group](#leave-a-group) - [Get Invite Code](#get-invite-code) - [Revoke Invite Code](#revoke-invite-code) - [Join Using Invitation Code](#join-using-invitation-code) - [Get Group Info by Invite Code](#get-group-info-by-invite-code) - [Query Metadata (participants, name, description...)](#query-metadata-participants-name-description) - [Join using groupInviteMessage](#join-using-groupinvitemessage) - [Get Request Join List](#get-request-join-list) - [Approve/Reject Request Join](#approvereject-request-join) - [Get All Participating Groups Metadata](#get-all-participating-groups-metadata) - [Toggle Ephemeral](#toggle-ephemeral) - [Change Add Mode](#change-add-mode) - [Privacy](#privacy) - [Block/Unblock User](#blockunblock-user) - [Get Privacy Settings](#get-privacy-settings) - [Get BlockList](#get-blocklist) - [Update LastSeen Privacy](#update-lastseen-privacy) - [Update Online Privacy](#update-online-privacy) - [Update Profile Picture Privacy](#update-profile-picture-privacy) - [Update Status Privacy](#update-status-privacy) - [Update Read Receipts Privacy](#update-read-receipts-privacy) - [Update Groups Add Privacy](#update-groups-add-privacy) - [Update Default Disappearing Mode](#update-default-disappearing-mode) - [Broadcast Lists & Stories](#broadcast-lists--stories) - [Send Broadcast & Stories](#send-broadcast--stories) - [Query a Broadcast List's Recipients & Name](#query-a-broadcast-lists-recipients--name) - [Writing Custom Functionality](#writing-custom-functionality) - [Enabling Debug Level in Baileys Logs](#enabling-debug-level-in-baileys-logs) - [How Whatsapp Communicate With Us](#how-whatsapp-communicate-with-us) - [Register a Callback for Websocket Events](#register-a-callback-for-websocket-events) ## Connecting Account WhatsApp provides a multi-device API that allows Baileys to be authenticated as a second WhatsApp client by scanning a **QR code** or **Pairing Code** with WhatsApp on your phone. > [!NOTE] > **[Here](#example-to-start) is a simple example of event handling** > [!TIP] > **You can see all supported socket configs [here](https://baileys.whiskeysockets.io/types/SocketConfig.html) (Recommended)** ### Starting socket with **QR-CODE** > [!TIP] > You can customize browser name if you connect with **QR-CODE**, with `Browser` constant, we have some browsers config, **see [here](https://baileys.whiskeysockets.io/types/BrowsersMap.html)** ```ts import makeWASocket from 'secret-company-ltd' const guns = makeWASocket({ // can provide additional config here browser: Browsers.ubuntu('My App'), printQRInTerminal: true }) ``` If the connection is successful, you will see a QR code printed on your terminal screen, scan it with WhatsApp on your phone and you'll be logged in! ### Starting socket with **Pairing Code** > [!IMPORTANT] > Pairing Code isn't Mobile API, it's a method to connect Whatsapp Web without QR-CODE, you can connect only with one device, see [here](https://faq.whatsapp.com/1324084875126592/?cms_platform=web) The phone number can't have `+` or `()` or `-`, only numbers, you must provide country code ```ts import makeWASocket from 'secret-company-ltd' const guns = makeWASocket({ // can provide additional config here printQRInTerminal: false //need to be false }) if (!guns.authState.creds.registered) { const number = 'XXXXXXXXXXX' const code = await guns.requestPairingCode(number) // or await guns.requestPairingCode(number, 'CODEOTPS') custom your pairing code console.log(code) } ``` ### Receive Full History 1. Set `syncFullHistory` as `true` 2. Baileys, by default, use chrome browser config - If you'd like to emulate a desktop connection (and receive more message history), this browser setting to your Socket config: ```ts const guns = makeWASocket({ ...otherOpts, // can use Windows, Ubuntu here too browser: Browsers.macOS('Desktop'), syncFullHistory: true }) ``` ## Important Notes About Socket Config ### Caching Group Metadata (Recommended) - If you use baileys for groups, we recommend you to set `cachedGroupMetadata` in socket config, you need to implement a cache like this: ```ts const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false}) const guns = makeWASocket({ cachedGroupMetadata: async (jid) => groupCache.get(jid) }) guns.ev.on('groups.update', async ([event]) => { const metadata = await guns.groupMetadata(event.id) groupCache.set(event.id, metadata) }) guns.ev.on('group-participants.update', async (event) => { const metadata = await guns.groupMetadata(event.id) groupCache.set(event.id, metadata) }) ``` ### Improve Retry System & Decrypt Poll Votes - If you want to improve sending message, retrying when error occurs and decrypt poll votes, you need to have a store and set `getMessage` config in socket like this: ```ts const guns = makeWASocket({ getMessage: async (key) => await getMessageFromStore(key) }) ``` ### Receive Notifications in Whatsapp App - If you want to receive notifications in whatsapp app, set `markOnlineOnConnect` to `false` ```ts const guns = makeWASocket({ markOnlineOnConnect: false }) ``` ## Saving & Restoring Sessions You obviously don't want to keep scanning the QR code every time you want to connect. So, you can load the credentials to log back in: ```ts import makeWASocket, { useMultiFileAuthState } from 'secret-company-ltd' const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys') // will use the given state to connect // so if valid credentials are available -- it'll connect without QR const guns = makeWASocket({ auth: state }) // this will be called as soon as the credentials are updated guns.ev.on('creds.update', saveCreds) ``` > [!IMPORTANT] > `useMultiFileAuthState` is a utility function to help save the auth state in a single folder, this function serves as a good guide to help write auth & key states for SQL/no-SQL databases, which I would recommend in any production grade system. > [!NOTE] > When a message is received/sent, due to signal sessions needing updating, the auth keys (`authState.keys`) will update. Whenever that happens, you must save the updated keys (`authState.keys.set()` is called). Not doing so will prevent your messages from reaching the recipient & cause other unexpected consequences. The `useMultiFileAuthState` function automatically takes care of that, but for any other serious implementation -- you will need to be very careful with the key state management. ## Handling Events - Baileys uses the EventEmitter syntax for events. They're all nicely typed up, so you shouldn't have any issues with an Intellisense editor like VS Code. > [!IMPORTANT] > **The events are [these](https://baileys.whiskeysockets.io/types/BaileysEventMap.html)**, it's important you see all events You can listen to these events like this: ```ts const guns = makeWASocket() guns.ev.on('messages.upsert', ({ messages }) => { console.log('got messages', messages) }) ``` ### Example to Start > [!NOTE] > This example includes basic auth storage too ```ts import makeWASocket, { DisconnectReason, useMultiFileAuthState } from 'secret-company-ltd' import { Boom } from '@hapi/boom' async function connectToWhatsApp () { const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys') const guns = makeWASocket({ // can provide additional config here auth: state, printQRInTerminal: true }) guns.ev.on('connection.update', (update) => { const { connection, lastDisconnect } = update if(connection === 'close') { const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect) // reconnect if not logged out if(shouldReconnect) { connectToWhatsApp() } } else if(connection === 'open') { console.log('opened connection') } }) guns.ev.on('messages.upsert', event => { for (const m of event.messages) { console.log(JSON.stringify(m, undefined, 2)) console.log('replying to', m.key.remoteJid) await guns.sendMessage(m.key.remoteJid!, { text: 'Hello Word' }) } }) // to storage creds (session info) when it updates guns.ev.on('creds.update', saveCreds) } // run in main file connectToWhatsApp() ``` ### For example if you use useSingleFileAuthState and useMongoFileAuthState ```ts import makeWASocket, { useSingleFileAuthState, useMongoFileAuthState } from 'secret-company-ltd' // Single Auth const { state, saveState } = await useSingleFileAuthState('./auth_info_baileys.json') const guns = makeWASocket({ auth: state, printQRInTerminal: true }) guns.ev.on('creds.update', saveState) // Mongo Auth import { MongoClient } from "mongodb" const connectAuth = async() => { global.client = new MongoClient('mongoURL') global.client.connect(err => { if (err) { console.warn("Warning: MongoDB link is invalid or cannot be connected.") } else { console.log('Successfully Connected To MongoDB Server') } }) } await client.connect() const collection = client.db("@secretcompany").collection("sessions") return collection } const Authentication = await connectAuth() const { state, saveCreds } = await useMongoFileAuthState(Authentication) const guns = makeWASocket({ auth: state, printQRInTerminal: true }) guns.ev.on('creds.update', saveCreds) ``` > [!IMPORTANT] > In `messages.upsert` it's recommended to use a loop like `for (const message of event.messages)` to handle all messages in array ### Decrypt Poll Votes - By default poll votes are encrypted and handled in `messages.update` ```ts import pino from "pino" import { makeInMemoryStore, getAggregateVotesInPollMessage } from 'secret-company' const logger = pino({ timestamp: () => `,"time":"${new Date().toJSON()}"` }).child({ class: "secretcompany" }) logger.level = "fatal" const store = makeInMemoryStore({ logger }) async function getMessage(key){ if (store) { const msg = await store.loadMessage(key.remoteJid, key.id) return msg?.message } return { conversation: "Secret Company" } } guns.ev.on("messages.update", async (chatUpdate) => { for(const { key, update } of chatUpdate) { if(update.pollUpdates && key.fromMe) { const pollCreation = await getMessage(key) if(pollCreation) { const pollUpdate = await getAggregateVotesInPollMessage({ message: pollCreation, pollUpdates: update.pollUpdates, }) const toCmd = pollUpdate.filter(v => v.voters.length !== 0)[0]?.name if (toCmd == undefined) return console.log(toCmd) } } } }) ``` ### Summary of Events on First Connection 1. When you connect first time, `connection.update` will be fired requesting you to restart sock 2. Then, history messages will be received in `messaging.history-set` ## Implementing a Data Store - Baileys does not come with a defacto storage for chats, contacts, or messages. However, a simple in-memory implementation has been provided. The store listens for chat updates, new messages, message updates, etc., to always have an up-to-date version of the data. > [!IMPORTANT] > I highly recommend building your own data store, as storing someone's entire chat history in memory is a terrible waste of RAM. It can be used as follows: ```ts import makeWASocket, { makeInMemoryStore } from 'secret-company' // the store maintains the data of the WA connection in memory // can be written out to a file & read from it const store = makeInMemoryStore({ }) // can be read from a file store.readFromFile('./baileys_store.json') // saves the state to a file every 10s setInterval(() => { store.writeToFile('./baileys_store.json') }, 10_000) const guns = makeWASocket({ }) // will listen from this socket // the store can listen from a new socket once the current socket outlives its lifetime store.bind(guns.ev) guns.ev.on('chats.upsert', () => { // can use 'store.chats' however you want, even after the socket dies out // 'chats' => a KeyedDB instance console.log('got chats', store.chats.all()) }) guns.ev.on('contacts.upsert', () => { console.log('got contacts', Object.values(store.contacts)) }) ``` The store also provides some simple functions such as `loadMessages` that utilize the store to speed up data retrieval. ## Whatsapp IDs Explain - `id` is the WhatsApp ID, called `jid` too, of the person or group you're sending the message to. - It must be in the format ```[country code][phone number]@s.whatsapp.net``` - Example for people: ```+19999999999@s.whatsapp.net```. - For groups, it must be in the format ``` 123456789-123345@g.us ```. - For broadcast lists, it's `[timestamp of creation]@broadcast`. - For stories, the ID is `status@broadcast`. ## Utility Functions - `getContentType`, returns the content type for any message - `getDevice`, returns the device from message - `makeCacheableSignalKeyStore`, make auth store more fast - `downloadContentFromMessage`, download content from any message ## Sending Messages - Send all types of messages with a single function - **[Here](https://baileys.whiskeysockets.io/types/AnyMessageContent.html) you can see all message contents supported, like text message** - **[Here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html) you can see all options supported, like quote message** ```ts const jid: string const content: AnyMessageContent const options: MiscMessageGenerationOptions guns.sendMessage(jid, content, options) ``` ### Non-Media Messages #### Text Message ```ts await guns.sendMessage(jid, { text: 'hello word' }) ``` #### Quote Message (works with all types) ```ts await guns.sendMessage(jid, { text: 'hello word' }, { quoted: message }) ``` #### Mention User (works with most types) - @number is to mention in text, it's optional ```ts await guns.sendMessage( jid, { text: '@12345678901', mentions: ['12345678901@s.whatsapp.net'] } ) ``` #### Forward Messages - You need to have message object, can be retrieved from [store](#implementing-a-data-store) or use a [message](https://baileys.whiskeysockets.io/types/WAMessage.html) object ```ts const msg = getMessageFromStore() // implement this on your end await guns.sendMessage(jid, { forward: msg, force: true or number }) // WA forward the message! ``` #### Location Message ```ts await guns.sendMessage( jid, { location: { degreesLatitude: 24.121231, degreesLongitude: 55.1121221 } } ) ``` #### Live Location Message ```ts await guns.sendMessage( jid, { location: { degreesLatitude: 24.121231, degreesLongitude: 55.1121221 }, live: true } ) ``` #### Contact Message ```ts const vcard = 'BEGIN:VCARD\n' // metadata of the contact card + 'VERSION:3.0\n' + 'FN:Jeff Singh\n' // full name + 'ORG:Ashoka Uni\n' // the organization of the contact + 'TELtype=CELLtype=VOICEwaid=911234567890:+91 12345 67890\n' // WhatsApp ID + phone number + 'END:VCARD' await guns.sendMessage( id, { contacts: { displayName: 'secretcompany', contacts: [{ vcard }] } } ) ``` #### Reaction Message - You need to pass the key of message, you can retrieve from [store](#implementing-a-data-store) or use a [key](https://baileys.whiskeysockets.io/types/WAMessageKey.html) object ```ts await guns.sendMessage( jid, { react: { text: '💖', // use an empty string to remove the reaction key: message.key } } ) ``` #### Pin Message - You need to pass the key of message, you can retrieve from [store](#implementing-a-data-store) or use a [key](https://baileys.whiskeysockets.io/types/WAMessageKey.html) object - Time can be: | Time | Seconds | |-------|----------------| | 24h | 86.400 | | 7d | 604.800 | | 30d | 2.592.000 | ```ts await guns.sendMessage( jid, { pin: { type: 1, // 2 to remove time: 86400, key: Key } } ) ``` ### Keep Message ```ts await guns.sendMessage( jid, { keep: { key: Key, type: 1 // or 2 } } ) ``` #### Poll Message ```ts await guns.sendMessage( jid, { poll: { name: 'My Poll', values: ['Option 1', 'Option 2', ...], selectableCount: 1, toAnnouncementGroup: false // or true } } ) ``` #### Poll Result Message ```ts await guns.sendMessage( jid, { pollResult: { name: 'Hi', values: [ [ 'Option 1', 1000 ], [ 'Option 2', 2000 ] ] } } ) ``` ### Call Message ```ts await guns.sendMessage( jid, { call: { name: 'Hay', type: 1 // 2 for video } } ) ``` ### Event Message ```ts await guns.sendMessage( jid, { event: { isCanceled: false, // or true name: 'holiday together!', description: 'who wants to come along?', location: { degreesLatitude: 24.121231, degreesLongitude: 55.1121221, name: 'name' }, startTime: number, endTime: number, extraGuestsAllowed: true // or false } } ) ``` ### Order Message ```ts await guns.sendMessage( jid, { order: { orderId: '574xxx', thumbnail: 'your_thumbnail', itemCount: 'your_count', status: 'your_status', // INQUIRY || ACCEPTED || DECLINED surface: 'CATALOG', message: 'your_caption', orderTitle: "your_title", sellerJid: 'your_jid'', token: 'your_token', totalAmount1000: 'your_amount', totalCurrencyCode: 'IDR' } } ) ``` ### Product Message ```ts await guns.sendMessage( jid, { product: { productImage: { // for using buffer >> productImage: your_buffer url: your_url }, productId: 'your_id', title: 'your_title', description: 'your_description', currencyCode: 'IDR', priceAmount1000: 'your_amount', retailerId: 'your_reid', // optional use if needed url: 'your_url', // optional use if needed productImageCount: 'your_imageCount', firstImageId: 'your_image', // optional use if needed salePriceAmount1000: 'your_priceSale', signedUrl: 'your_url' // optional use if needed }, businessOwnerJid: 'your_jid' } ) ``` ### Payment Message ```ts await guns.sendMessage( jid, { payment: { note: 'Hi!', currency: 'IDR', // optional offset: 0, // optional amount: '10000', // optional expiry: 0, // optional from: '628xxxx@s.whatsapp.net', // optional image: { // optional placeholderArgb: "your_background", // optional textArgb: "your_text", // optional subtextArgb: "your_subtext" // optional } } } ) ``` #### Payment Invite Message ```ts await guns.sendMessage( id, { paymentInvite: { type: number, // 1 || 2 || 3 expiry: 0 } } ) ``` ### Admin Invite Message ```ts await guns.sendMessage( jid, { adminInvite: { jid: '123xxx@newsletter', name: 'newsletter_name', caption: 'Please be my channel admin', expiration: 86400, jpegThumbnail: Buffer // optional } } ) ``` ### Group Invite Message ```ts await guns.sendMessage( jid, { groupInvite: { jid: '123xxx@g.us', name: 'group_name', caption: 'Please Join My Whatsapp Group', code: 'code_invite', expiration: 86400, jpegThumbnail: Buffer, // optional } } ) ``` ### Sticker Pack Message ```ts // I don't know why the sticker doesn't appear await guns.sendMessage( jid, { stickerPack: { name: 'Hiii', publisher: 'By secretcompany', description: 'Hello', cover: Buffer, // Image buffer stickers: [{ data: { url: 'https://example.com/1234kjd.webp' }, emojis: ['❤'], // optional accessibilityLabel: '' // optional }, { data: Buffer, emojis: ['❤'], // optional accessibilityLabel: '' // optional }] } } ) ``` ### Share Phone Number Message ```ts await guns.sendMessage( jid, { sharePhoneNumber: { } } ) ``` ### Request Phone Number Message ```ts await guns.sendMessage( jid, { requestPhoneNumber: { } } ) ``` ### Buttons Reply Message ```ts // List await guns.sendMessage( jid, { buttonReply: { name: 'Hii', description: 'description', rowId: 'ID' }, type: 'list' } ) // Plain await guns.sendMessage( jid, { buttonReply: { displayText: 'Hii', id: 'ID' }, type: 'plain' } ) // Template await guns.sendMessage( jid, { buttonReply: { displayText: 'Hii', id: 'ID', index: 'number' }, type: 'template' } ) // Interactive await guns.sendMessage( jid, { buttonReply: { body: 'Hii', nativeFlows: { name: 'menu_options', paramsJson: JSON.stringify({ id: 'ID', description: 'description' }) version: 1 // 2 | 3 } }, type: 'interactive' } ) ``` ### Buttons Message ```ts await guns.sendMessage( jid, { text: 'This is a button message!', // image: buffer or // image: { url: url } If you want to use images caption: 'caption', // Use this if you are using an image or video footer: 'Hello World!', buttons: [{ buttonId: 'Id1', buttonText: { displayText: 'Button 1' } }, { buttonId: 'Id2', buttonText: { displayText: 'Button 2' } }, { buttonId: 'Id3', buttonText: { displayText: 'Button 3' } }] } ) ``` ### Buttons List Message ```ts // Just working in a private chat await guns.sendMessage( jid, { text: 'This is a list!', footer: 'Hello World!', title: 'Amazing boldfaced list title', buttonText: 'Required, text on the button to view the list', sections: [ { title: 'Section 1', rows: [{ title: 'Option 1', rowId: 'option1' }, { title: 'Option 2', rowId: 'option2', description: 'This is a description' }] }, { title: 'Section 2', rows: [{ title: 'Option 3', rowId: 'option3' }, { title: 'Option 4', rowId: 'option4', description: 'This is a description V2' }] }] } ) ``` ### Buttons Product List Message ```ts // Just working in a private chat await guns.sendMessage( jid, { text: 'This is a list!', footer: 'Hello World!', title: 'Amazing boldfaced list title', buttonText: 'Required, text on the button to view the list', productList: [{ title: 'This is a title', products: [ { productId: '1234' }, { productId: '5678' } ] }], businessOwnerJid: '628xxx@s.whatsapp.net', thumbnail: 'https//example.com/jdbenkksjs.jpg' // or buffer } ) ``` ### Buttons Cards Message ```ts await guns.sendMessage( jid, { text: 'Body Message', title: 'Title Message', subtile: 'Subtitle Message', footer: 'Footer Message', cards: [ { image: { url: 'https//example.com/jdbenkksjs.jpg' }, // or buffer title: 'Title Cards', body: 'Body Cards', footer: 'Footer Cards', buttons: [ { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Display Button', id: 'ID' }) }, { name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: 'Display Button', url: 'https://www.example.com' }) } ] }, { video: { url: 'https//example.com/jdbenkksjs.mp4' }, // or buffer title: 'Title Cards', body: 'Body Cards', footer: 'Footer Cards', buttons: [ { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Display Button', id: 'ID' }) }, { name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: 'Display Button', url: 'https://www.example.com' }) } ] } ] } ) ``` ### Buttons Template Message ```ts await guns.sendMessage( jid, { text: 'This is a template message!', footer: 'Hello World!', templateButtons: [{ index: 1, urlButton: { displayText: 'Follow Me', url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y' }, }, { index: 2, callButton: { displayText: 'Call Me!', phoneNumber: '628xxx' }, }, { index: 3, quickReplyButton: { displayText: 'This is a reply, just like normal buttons!', id: 'id-like-buttons-message' }, }] } ) ``` ### Buttons Interactive Message ```ts await guns.sendMessage( jid, { text: 'This is an Interactive message!', title: 'Hiii', subtitle: 'There is a subtitle', footer: 'Hello World!', interactiveButtons: [ { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Click Me!', id: 'your_id' }) }, { name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: 'Follow Me', url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y', merchant_url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y' }) }, { name: 'cta_copy', buttonParamsJson: JSON.stringify({ display_text: 'Click Me!', copy_code: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y' }) }, { name: 'cta_call', buttonParamsJson: JSON.stringify({ display_text: 'Call Me!', phone_number: '628xxx' }) }, { name: 'cta_catalog', buttonParamsJson: JSON.stringify({ business_phone_number: '628xxx' }) }, { name: 'cta_reminder', buttonParamsJson: JSON.stringify({ display_text: '...' }) }, { name: 'cta_cancel_reminder', buttonParamsJson: JSON.stringify({ display_text: '...' }) }, { name: 'address_message', buttonParamsJson: JSON.stringify({ display_text: '...' }) }, { name: 'send_location', buttonParamsJson: JSON.stringify({ display_text: '...' }) }, { name: 'open_webview', buttonParamsJson: JSON.stringify({ title: 'Follow Me!', link: { in_app_webview: true, // or false url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y' } }) }, { name: 'mpm', buttonParamsJson: JSON.stringify({ product_id: '8816262248471474' }) }, { name: 'wa_payment_transaction_details', buttonParamsJson: JSON.stringify({ transaction_id: '12345848' }) }, { name: 'automated_greeting_message_view_catalog', buttonParamsJson: JSON.stringify({ business_phone_number: '628xxx', catalog_product_id: '12345' }) }, { name: 'galaxy_message', buttonParamsJson: JSON.stringify({ mode: 'published', flow_message_version: '3', flow_token: '1:1307913409923914:293680f87029f5a13d1ec5e35e718af3', flow_id: '1307913409923914', flow_cta: 'secretcompany kawaii >\\<', flow_action: 'navigate', flow_action_payload: { screen: 'QUESTION_ONE', params: { user_id: '123456789', referral: 'campaign_xyz' } }, flow_metadata: { flow_json_version: '201', data_api_protocol: 'v2', flow_name: 'Lead Qualification [en]', data_api_version: 'v2', categories: ['Lead Generation', 'Sales'] } }) }, { name: 'single_select', buttonParamsJson: JSON.stringify({ title: 'Click Me!', sections: [ { title: 'Title 1', highlight_label: 'Highlight label 1', rows: [ { header: 'Header 1', title: 'Title 1', description: 'Description 1', id: 'Id 1' }, { header: 'Header 2', title: 'Title 2', description: 'Description 2', id: 'Id 2' } ] } ] }) } ] } ) // If you want to use an image await guns.sendMessage( jid, { image: { url: 'https//example.com/jdbenkksjs.jpg' }, caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', interactiveButtons: [ { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'DisplayText', id: 'ID1' }) } ], hasMediaAttachment: false // or true } ) // If you want to use an video await guns.sendMessage( jid, { video: { url: 'https//example.com/jdbenkksjs.mp4' }, caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', interactiveButtons: [ { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'DisplayText', id: 'ID1' }) } ], hasMediaAttachment: false // or true } ) // If you want to use an document await guns.sendMessage( jid, { document: { url: 'https//example.com/jdbenkksjs.jpg' }, mimetype: 'image/jpeg', jpegThumbnail: await guns.resize('https//example.com/jdbenkksjs.jpg', 320, 320), caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', interactiveButtons: [ { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'DisplayText', id: 'ID1' }) } ], hasMediaAttachment: false // or true } ) // If you want to use an location await guns.sendMessage( jid, { location: { degressLatitude: -0, degressLongitude: 0, name: 'Hi' }, caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', interactiveButtons: [ { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'DisplayText', id: 'ID1' }) } ], hasMediaAttachment: false // or true } ) // if you want to use an product await guns.sendMessage( jid, { product: { productImage: { url: 'https//example.com/jdbenkksjs.jpg' }, productId: '836xxx', title: 'Title', description: 'Description', currencyCode: 'IDR', priceAmount1000: '283xxx', retailerId: 'secretcompany', url: 'https://example.com', productImageCount: 1 }, businessOwnerJid: '628xxx@s.whatsapp.net', caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', interactiveButtons: [ { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'DisplayText', id: 'ID1' }) } ], hasMediaAttachment: false // or true } ) ``` ### Buttons Interactive Message PIX ```ts await guns.sendMessage( jid, { text: '', // This string is required. Even it's empty. interactiveButtons: [ { name: 'payment_info', buttonParamsJson: JSON.stringify({ payment_settings: [{ type: "pix_static_code", pix_static_code: { merchant_name: 'secretcompany', key: 'example@secret.com', key_type: 'EMAIL' // PHONE || EMAIL || CPF || EVP } }] }) } ], } ) ``` ### Buttons Interactive Message PAY ```ts await guns.sendMessage( jid, { text: '', // This string is required. Even it's empty. interactiveButtons: [ { name: 'review_and_pay', buttonParamsJson: JSON.stringify({ currency: 'IDR', payment_configuration: '', payment_type: '', total_amount: { value: '999999999', offset: '100' }, reference_id: '45XXXXX', type: 'physical-goods', payment_method: 'confirm', payment_status: 'captured', payment_timestamp: Math.floor(Date.now() / 1000), order: { status: 'completed', description: '', subtotal: { value: '0', offset: '100' }, order_type: 'PAYMENT_REQUEST', items: [{ retailer_id: 'your_retailer_id', name: 'secretcompany', amount: { value: '999999999', offset: '100' }, quantity: '1', }] }, additional_note: 'secretcompany', native_payment_methods: [], share_payment_status: false }) } ], } ) ``` ### Status Mentions Message ```ts const jidat = [ '123451679@g.us', '124848899@g.us', '111384848@g.us', '62689xxxx@s.whatsapp.net', '62xxxxxxx@s.whatsapp.net' ] // Text await guns.sendStatusMentions( { text: 'Hello Everyone :3', font: 2, // optional textColor: 'FF0000', // optional backgroundColor: '#000000' // optional }, jids // Limit to 5 mentions per status ) // Image await guns.sendStatusMentions( { Image: { url: 'https://example.com/ruriooe.jpg' }, or image buffer caption: 'Hello Everyone :3' // optional }, jids // Limit to 5 mentions per status ) // Video await guns.sendStatusMentions( { video: { url: 'https://example.com/ruriooe.mp4' }, or video buffer caption: 'Hello Everyone :3' // optional }, jids // Limit to 5 mentions per status ) // Audio await guns.sendStatusMentions( { audio: { url: 'https://example.com/ruriooe.mp3' }, or audio buffer backgroundColor: '#000000', // optional mimetype: 'audio/mp4', ppt: true }, jids // Limit to 5 mentions per status ) ``` ### Send Album Message ```ts await guns.sendAlbumMessage( jid, [ { image: { url: 'https//example.com/jdbenkksjs.jpg' }, caption: 'Hello World' }, { image: Buffer, caption: 'Hello World' }, { video: { url: 'https//example.com/jdbenkksjs.mp4' }, caption: 'Hello World' }, { video: Buffer, caption: 'Hello World' } ], { quoted: message, delay: 2000 } ) ``` ### Shop Message ```ts await guns.sendMessage( jid, { text: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', shop: { surface: 1, // 2 | 3 | 4 id: 'https://example.com' }, viewOnce: true } ) // Image await guns.sendMessage( jid, { image: { url: 'https//example.com/jdbenkksjs.jpg' }, caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', shop: { surface: 1, // 2 | 3 | 4 id: 'https://example.com' }, hasMediaAttachment: false, // or true viewOnce: true } ) // Video await guns.sendMessage( jid, { video: { url: 'https//example.com/jdbenkksjs.jpg' }, caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', shop: { surface: 1, // 2 | 3 | 4 id: 'https://example.com' }, hasMediaAttachment: false, // or true viewOnce: true } ) // Document await guns.sendMessage( jid, { document: { url: 'https//example.com/jdbenkksjs.jpg' }, mimetype: 'image/jpeg', jpegThumbnail: await guns.resize('https//example.com/jdbenkksjs.jpg', 320, 320), caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', shop: { surface: 1, // 2 | 3 | 4 id: 'https://example.com' }, hasMediaAttachment: false, // or true, viewOnce: true } ) // Location await guns.sendMessage( jid, { location: { degressLatitude: -0, degressLongitude: 0, name: 'Hi' }, caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', shop: { surface: 1, // 2 | 3 | 4 id: 'https://example.com' }, hasMediaAttachment: false, // or true viewOnce: true } ) // Product await guns.sendMessage( jid, { product: { productImage: { url: 'https//example.com/jdbenkksjs.jpg' }, productId: '836xxx', title: 'Title', description: 'Description', currencyCode: 'IDR', priceAmount1000: '283xxx', retailerId: 'secretcompany', url: 'https://example.com', productImageCount: 1 }, businessOwnerJid: '628xxx@s.whatsapp.net', caption: 'Body', title: 'Title', subtitle: 'Subtitle', footer: 'Footer', shop: { surface: 1, // 2 | 3 | 4 id: 'https://example.com' }, hasMediaAttachment: false, //