@aidulcandra/simple-wa-bot

26.6.2 • Public • Published

simple-wa-bot

By aidulcandra. Email me at aidulcandra@gmail.com. Simpler way to code your baileys bot. (This module wraps baileys)

What's New in 26.x

InputReaderProgram

  • New modifiers withGif(), withPoll()

Message

  • message.replyGif()
  • message.replyPoll()
  • Whatsapp is switching to LID as a replacement for JID in the future, if your bot receives messages inside groups that use LID, the message.sender.lid will be available, message.sender.id will still contain the JID of the sender for now. Since the bot needs to find the JID first by querying the group data, it will take longer for the bot to produce the JID (but the group data will of course be cached for faster subsequent processes)
  • message.poll for poll type messages
  • message.vote for vote type messages
  • message.receivedWhenOnline

Bot

  • bot.sendGif()
  • Get group data with bot.getGroupData(groupId)
  • Switched from QR Code login method to Pairing Code
  • bot.command()'s 4th argument: aliases, string or array of strings of command aliases
  • bot.sendPoll()

Module

  • Updated module from @whiskeysockets/baileys to baileys

Other

  • Fix bugs
  • Readme cleanup

Installation

npm install @aidulcandra/simple-wa-bot

Config File

When first run, a config file bot-config.json will be created if it does not exist. Default config is as follows. You can save this as bot-config.json to configure things beforehand.

{
  "ownerIds": [],
  "parseMentions": true,
  "recordPushnames": true,
  "autoRead": false,
  "processOfflineMessages": true,
  "storeSize": 100,
  "commandPrefixes": ["/"],
  "commandMenu": {
    "menuTemplate": "> COMMAND LIST\n\n@categorylist\n\n_Created by: @aidulcandra_",
    "categoryTemplate": "[@category]----\n@commandlist\n------------",
    "categorySeparator": "\n\n",
    "commandTemplate": "`@prefix@command` - @description",
    "commandSeparator": "\n"
  }
}

Description:

  • ownerIds : Array of owner/co-owners ids
  • parseMentions : Whether to parse mentions into "@" + username. Example: Hello @Aidul
  • recordPushnames : Whether to keep track of user pushnames and the changes. Will allow you to get a user's last pushnames outside the event of receiving their message.
  • autoRead : Auto read received messages (send double blue-tick mark)
  • processOfflineMessages : Whether to detect and process messages that were sent when the bot is offline (when the program is not running).
  • storeSize : The size of the message store. This store is useful for functionalities that require original message objects by referencing their message id and the chatroom id, like getting the original of a quoted message, or for a vote to update the poll message.
  • commandPrefixes : Array of prefixes that can be used to invoke commands
  • commandMenu : Command menu template
    • menuTemplate : @categorylist will be replaced by category list
    • categoryTemplate : @category will be replaced by category name, @commandlist will be replaced by the list of the commands, @prefix will be replaced with the first prefix in the prefix list
    • categorySeparator : Separator for each category list
    • commandTemplate : @command will be replaced by command name, @description will be replaced by the description of the command
    • commandSeparator : Separator for each command item

Example

const bot = require("@aidulcandra/simple-wa-bot");

// Receiving exact match of text and replying
bot.receive("Hello").reply("Hi there");

// Receiving text with similarity value (value is 0 thru 1)
bot.receive("Hello").similarity(0.6).reply("Hi there");

// Ignore case
bot.receive("Good morning").ignoreCase().reply("Good morning to you too!");

// Ignore case and check similarity
bot.receive("How are you?").ignoreCase().similarity(0.7).reply("I'm fine");

// Reply with image
bot
  .receive("send pic")
  .reply() // Insert string for caption
  .image("https://url.to/your/image") // Or path to your local image

// Multi input (will respond to any of the inputs)
bot.receive(["text1", "text2", "text3"]).reply("Yes")
bot.receive("text1", "text2", "text3").reply("Yes")

// Only respond in private chats
bot.receive("hello").privateOnly().reply("hi");

// Only respond in group chats
bot.receive("hello").groupOnly().reply("hi");

// Only respond in specific chat rooms
bot.receive("hello").in("ABCDE@g.us").reply("hi");

// Only respond to specific sender id(s)
bot.receive("hello").from("6282123456789@s.whatsapp.net").reply("hi");
bot.receive("hello").from("xxx@s.wa.net", "yyy@s.wa.net").reply("hi");
bot
  .receive("hello")
  .from(["6282123456789@s.whatsapp.net", "6282987654321@s.whatsapp.net"])
  .reply("hi");

// Respond to texts beginning with specific substring
bot.receiveBeginning("Do you").ignoreCase().reply("Maybe");

// Respond to texts containing specific substring
bot
  .receiveContaining("ice cream")
  .ignoreCase()
  .reply("Did you say ICE CREAM???");

// Respond to texts ending with specific substring
bot.receiveEnding("?").ignoreCase().reply("You were asking?");

// Testing incoming message on a regex pattern
bot.receive(/Do you know .+ \?/i).reply("No.");

// RegEx pattern matching, use <<number>> to insert captured match (in order starting from 1)
bot.receive(/My name is (\w+)/).reply("Nice to meet you, <<1>>!");

// Custom condition (must input a function)
bot.receive("hey").if(isAllowedToReply).reply("heyo");
bot
  .receive("test")
  .if(function () {
    return true;
  })
  .reply("test back");

// first argument is the message object
function isAllowedToReply(msg) {
  // Some stuff
  return true
}

// Random reply
bot.receive("Hi").ignoreCase().replyRandom("Hey", "Hello", "Sup?"); // Can input array

// Default response if no programs are executed
bot.defaultResponse("I don't understand.");

//Don't forget to start the bot after programming responses
bot.start();

// Instead of bot.start(), you can test your bot in the console using this
bot.test();

Custom Script

// Run script. 1st argument is the message object.
bot.receive("date").run(function (message) {
    const name = message.sender.name
    const date = Date()
    message.reply(`Hello, ${name}! Today's date is ${date}`)
})
// 2nd argument of the run function is the array of captured matches when using regex as input
bot.receive(/my name is (\w+)/i).run(function (message, matches)) {
    message.reply(`Hello, ${matches[0]}!`)
}
// 3rd argument is the group if the message is received in a group
bot.receive("group name").run(function (msg, m, group) {
    msg.reply(`The group name is ${group.name}`)
})
// 4th argument is the bot object
function (msg, m, group, bot) {}

// Can also provide path to module that exports a function
bot.receive("import").run("commands/import.js")
// Inside commands/import.js:
module.exports = async function (msg, m, group) {
    msg.reply("I was called from outside")
}

// If the module exports an object with multiple functions, you can use the 2nd parameter to identify the function name
bot.receive("calculate").run("commands/my-module.js", "calculate")

The message Object's Properties and Methods

Name Description Example
message.id ID of the message object
message.text The text or caption of the message
message.room Chat ID where this message was sent to "628123456789@s.whatsapp.net" (private chats) / "123412341234@g.us" (group chats)
message.sender An object of the sender's info
message.sender.name Sender's name
message.sender.id Sender's ID "628123456789@s.whatsapp.net"
message.sender.isMe Whether the sender is the bot itself.
message.sender.isBlacklisted Whether the sender is blacklisted
message.sender.isOwner Whether the sender is the owner or a co-owner
message.sender.getPPUrl() Get the profile picture url of the sender
message.getQuoted() Get the quoted message object. If the quoted message is still stored in the store it will return the original message object, otherwise it will try to replicate the original. The replicant is a simplified and incomplete version of the original.
message.quoted A replicated version of the quoted message
message.isEdit Whether the message is an edit
message.receivedWhenOnline Whether this message was received when the bot is online
message.type Type of the message "text", "image", "video", etc.
message.isMedia Whether this message is a media message (image, video, document, audio, sticker)
message.image? Image object of the message if the type is "image"
message.image?.getBuffer() Get the buffer object of the image
message.image?.saveTo(path) Save the image to path
message.video? For "video" type message
message.video?.getBuffer()
message.video?.getStream()
message.video?.saveTo(path)
message.audio? For "audio" type message
message.audio?.duration Audio length (in seconds)
message.audio?.getBuffer()
message.audio?.getStream()
message.audio?.saveTo(path)
message.sticker? For "sticker" type message
message.sticker?.getBuffer()
message.sticker?.getStream()
message.sticker?.saveTo(path)
message.document? For "document" type message
message.document?.getBuffer()
message.document?.getStream()
message.document?.saveTo(path)
message.contacts? Contacts for "contacts" type message [{name:"Contact-1",number:"+123456789"},{name:"Contact-2",number:"+123456789"}]
message.location? Location for "location" type message
message.location?.longitude
message.location?.latitude
message.reactedId? The ID of the reacted message this message is reacting to, if this is a "reaction" type message.
message.poll? Poll for "poll" type message
message.poll?.title
message.poll?.choices array of poll vote options ["coffee", "tea"]
message.poll?.multiple whether this poll allows choosing multiple options
message.poll?.votes The summary of choices and their voters
message.vote? A vote on a poll, for "vote" type message
message.vote?.pollId ID of the poll message
message.vote?.list array of chosen options of this voter ["coffee","tea"]
message.mentions Array of mentioned ids
message.groupMentions Array of mentioned group ids
message.protocolData? If message type is 'protocol', this property will be available. This contains settings modified by a protocol message
message.protocolData?.chatDisapperingTime? This chat's disappearing time in miliseconds.
message.getBaileysMessage() Get the original baileys' MessageInfo object
message.reply(text) Reply to the message message.reply("Of course")
message.replyImage(source, caption) Reply with an image. source can be a Buffer or a string of url/path
message.replyVideo(source, caption) Reply with a video
message.replyGif(source, caption) Reply with a gif
message.replyAudio(source, mimetype?) Reply with an audio. Default mimetype is audio/mp4
message.replySticker(source, options) Reply with a sticker. Options:
{
   pack: string,
   author: string,
   type: 'default'/'crop'/'full'/'circle'/'rounded',
   background: hex color/css color name string,
   quality: number (0-100)
}
message.replyDocument(source, mimetype, fileName, caption) Reply with a document.
message.replyContacts(contacts) Reply with contact(s). contacts is an array of object {name, number}
message.replyLocation(latitude,longitude)
message.replyPoll(title,choices,multiple) Reply with a poll. Title is string. Choices is array of strings. Multiple is whether the poll allows voting multiple options.
message.edit(text) Edit this message (text only)
message.forward(to) Forward this message to target id
message.react(emoji) React to this message message.react("😂")
message.delete() Delete this message. Remember to delete others' messages the bot needs to be an admin of the group
message.read() "Read" the message. This will send the double blue-ticks mark to the sender's end.
message.saveTextTo(path) Save the text in a text file
message.saveToStore() Save this message to store. poll type messages will automatically be saved.
message.removeFromStore() Remove this message from store

The group Object's Properties and Methods

Name Description Example
group.id Id of the group "1234@g.us"
group.getSubject() Get the subject (name) of the group
group.getParticipants() Get the list of participants and their admin status
group.mute() Only allow admins to send messages
group.unmute() Allow members to send messages

The bot Object's Properties and Methods

Name Description Example
bot.getSocket() Returns the socket object that is created by baileys. You can use this to implement custom functionalities.
bot.start() Start the bot.
bot.test() Test the bot in the console (limited simulation)
bot.getConnectionState() Returns "open"/"connecting"/"closed"
bot.settings Contains settings that can be tweaked real time.
bot.settings.ownerIds Array of ids of bot owners / co-owners
bot.settings.parseMentions Whether to parse mention numbers into username if has been recorded. It's recommended to set recordPushnames to true as well.
bot.settings.recordPushnames Whether to keep track of pushnames
bot.settings.commandPrefixes Array of prefixes for popular command-style input ["/", ".", "!"] (Empty array for no prefix). Use in conjunction with bot.command()
bot.receive(input(s)) Register new message-response program See examples above. This returns a Program object which can be chained to methods to modify this particular program.
bot.receiveBeginning(input(s)) Register new program with the input as message beginning with a string
bot.receiveContaining(input(s)) Register new program with the input as message containing with a string
bot.receiveEnding(input(s)) Register new program with the input as message ending with a string
bot.receiveAny() Register new program responding to any message
bot.command(name, description, category, aliases) Register new program responding to a command-style input. Only input the command name, the program will automatically detect the prefix based on bot.settings.commandPrefixes. Description and category will be displayed in the menu maker. bot.command("check") will read input /check from user. You can also specify one or more parameters separated with space(s) and they will be treated like match captures for regex. Example: /check foo bar will make the match array ["foo", "bar"]. You can also use them using templating in your string (<<1>>, <<2>>, etc.). You can change the list of accepted prefixes in bot.settings.commandPrefixes. The aliases is an array of strings of this command's aliases (alternative command names)
bot.sent(input(s)) Register new self-message response program (when a message was sent from the bot's number itself). Returns a Program
bot.defaultResponse(text) If any other programs were not executed, send this text
bot.schedule(cronTime, timezone?) Trigger this program time-based. Uses cron time format documentation. Note: the format allows 1 extra field for second as the first field. So there can be 5 or 6 fields. timezone is the timezone name. Check here or leave it (by default local timezone)
  • bot.schedule("*/5 * * * * *") Triggers every five seconds
  • bot.schedule("30 18 * * sun") Triggers every Sunday at 6:30 PM
bot.removeProgram(uid) Unregister command with the specified uid. Each program has their own uid after creation.
bot.setVar(name, value) Set a variable setVar("count", 5)
bot.getVar(name) Get a variable's value getVar("my_var")
bot.deleteVar(name) Delete a variable
bot.sendText(targetId, text) Send a text to the chat id bot.sendText("628212345678@s.whatsapp.net", "Hello world")
bot.sendImage(targetId, source, caption) Send an image from given link to the chat id. source can be a buffer or a string of path/url `bot.sendImage("628212345678@s.whatsapp.net", "https://picsum.photos/300")
bot.sendVideo(targetId, source, caption) Send a video
bot.sendGif(targetId, source, caption) Send a gif
bot.sendAudio(targetId, source, mimetype) Send an audio. Default mimetype: "audio/mp4"
bot.sendSticker(targetId, source, options) Send a sticker. Source is path to image, or an image buffer. Options:
{
   pack: string,
   author: string,
   type: 'default'/'crop'/'full'/'circle'/'rounded',
   background: hex color/css color name string,
   quality: number (0-100)
}
bot.sendDocument(targetId, source, mimetype, fileName, caption) Send a document
bot.sendContacts(targetId, contacts) Send one or more contacts. Contacts argument is an array of {name, number}. The number can include symbols (ex:"+628123456789")
bot.sendLocation(targetId, latitude, longitude) Send a location message. Latitude and longitude are in degrees.
bot.sendPoll(targetId,title,choices,multiple) Send a poll. Title is string, choices is array of strings, multiple is whether users can vote more than one option. Poll messages are automatically saved to store, which is necessary to update it with new votes.
bot.updateStatus(newStatus) Change your status text
bot.updateName(newName) Change your display name
bot.checkAdmin(id, groupId) Check whether id is an admin of a group
bot.checkOwner(id) Check whether id is the owner or a co-owner
bot.getPushnames() Get the list of recorded pushnames
bot.getPushname(id) Get last recorded pushname for this id
bot.getId() Get the id of the bot
bot.getPPUrl(id, hq) Get profile picture url from a user. Set hq to true to get a high res image.
bot.getStatus(id) Get status text from a user
bot.getGroupData(id) Get info on a group chat with the specified id
bot.waitForMessage(roomId, options) Wait for a message to appear in a room then return the message object. options: timeout in ms (default 10000), and filter, a function that can be used to filter messages bot.waitForMessage(roomId, {filter:msg=>msg.sender.id===ownerId})
bot.blacklistGetList() Get an array of blacklisted ids bot.blacklistAdd(ids)
bot.blacklistRemove(ids) Remove number(s) / id(s) from the blacklist
bot.blacklistCheck(id) Check if an id is blacklisted
bot.createCommandMenu() Create a string of auto generated menu for command list See here
bot.addOwner(ids) Add id(s) to owner list. Can use arrays.
bot.removeOwner(ids) Remove id(s) from owner list.
bot.addPrefix(prefix) Add new prefix(es). Can use arrays.
bot.removePrefix(prefix) Remove prefix(es).
bot.saveSettings() Save bot config file.
bot.getMessageFromStore(id, room) Get a message from the store, with specified message id, and room id
bot.saveMessageToStore(msg) Save a message object to the store
bot.removeMessageFromStore(msg) Remove a message object from the store

Programs

In this module there are types of Programs that can be created using the bot's trigger definers:

  • bot.receive(), bot.receiveBeginning(), bot.receiveContaining(), bot.receiveEnding(), bot.receiveAny(), bot.command() and bot.sent() creates an InputReaderProgram
  • bot.started() creates a StartupProgram
  • bot.schedule() creates a ScheduledProgram

You will then chain methods called "modifiers" to these Programs. See the examples above.

Methods and Properties Of Program Object (Program Modifiers)

These modifiers works for all type of Programs

Method/Property Description Example
uid Unique identifier for each program "a2090b87-e3bf-4ab7-9e4a-4e08defaa13e"
ifVarIs(name, value) Respond if variable's value is equal to something ifVarIs("customers", 0)
ifVarExists(name) Respond if a variable exists ifVarExists("money")
ifVarNotExists(name) Respond if a variable does not exist ifVarNotExists("money")
if(conditionFunction) Custom condition (must input a function name). The function's only parameter is the message if(checkCustomers)
showTyping() Show the is typing ... text before sending response
showRecording() Show the is recording ... text before sending response
text(text) Send a text message as a response
textRandom(text) Randomly picks the response, can also pick from arrays textRandom("choice1", "choice2", choice3")
image(link) Set the image to be sent in the response. Uses link or path
video(link) Set the video to be sent in the response.
audio(link, mimetype) Set the audio to be sent in the response. Mimetype: default set to audio/mp4
sticker(link, options) Set the sticker to be sent in the response. Options: pack = string; author = string; type = 'default'/'crop'/'full'/'circle'/'rounded'; background=hex color string; quality = number sticker(link, {type:'crop', author:'SimpleBot'})
document(link, mimetype, fileName) Set the document to be sent in the response
contacts(contacts) Send a contact(s) (vcards) as a response. contacts argument is an array of {name, number}
location(latitude, longitude)
poll(title, choices, multiple) Send a poll. title is string, choices is arrays of strings, multiple is boolean - whether the poll allows voting multiple options.
sendMenu() Send the command menu. See here.
to(ids) Assign id(s) to send responses to. Can be used to broadcast messages.
setVar(name,value) Set a variable when responding to the input
blacklist(ids) Assign id(s) to be blacklisted (multiple arguments or array). If not specified, blacklist the sender instead.
whitelist(ids) Assign id(s) to be whitelisted. If not specified, whitelist the sender instead.
run(callback or path) Run a custom script. The callback's arguments are message, param, group, and bot. However if this Program is not an InputReaderProgram, the first 3 arguments will be undefined. See above.
stopHere() Stop responding to any other programs after this

InputReaderProgram's modifiers

Created with bot.receive(), bot.receiveAny(), bot.receiveBeginning(), bot.receiveEnding(), bot.receiveContaining(), bot.sent(). This is basically responding to an incoming message.

Method Description Example
in(ids) Respond only inside this chat id(s). Can input array or multiple arguments
from(ids) Only respond to this id(s). This will check the sender id, not the room id
notIn(ids) Don't respond inside this chat id(s)
notFrom(ids) Don't respond to this id(s)
privateOnly() Respond only to private messages
groupOnly() Respond only to group messages
adminOnly() Respond only to admins' messages (must be in a group)
ownerOnly() Respond only to the owner or co-owners
mentionedOnly() Respond only to messages mentioning the bot. Keep in mind that the mentions are included in the text, so using exact match of text can't be done with this (using bot.receive()). It's recommended to use this with regex type inputs, or bot.receiveContaining()
quotedOnly() Respond only to messages quoting the bot's message
withImage() Only respond to image messages
withVideo() Only respond to video messages
withGif() Only respond to GIF images
withAudio() Only respond to audio messages
withSticker() Only respond to sticker messages
withContacts() Only respond to contact messages
withLocation() Only respond to location messages
withPoll() Only respon to poll messages
includeBlacklist() Allow receiving the message from blacklisted ids
reply(text) Reply to this message. This can be used to quote to the message when sending media messages, for example with image() modifier (the text then becomes optional)
replyRandom(text) Same as above, but picked randomly from arguments. Can be arrays too.
react(emoji) React to this message react("😁")
forward() Forward this message. Use to() modifier to specify target id(s)
delete() Delete this message
read() Read this message (send blue ticks mark)
ignoreCase() Tell this program to ignore the case
stripMentions() Remove mentions from text
hideCommand() Hide this command from menu maker

ScheduledProgram's modifiers

Created with bot.schedule(). This will trigger the response based on provided interval.

Modifier Description Example
No special modifiers (probably will be added later)

Templating Notation

Notation Description Example
"<<number>>" Insert a captured match when input is a RegExp. Starting from number 1 "So your name is <<1>>?"
"%%var_name%%" Insert the value of a variable that has been set using bot.setVar(). Bear in mind that you should not use a variable to program your responses with modifiers like reply() if it's supposed to be dynamic. Because it will only display the value at the time you program the response. For example, if you do bot.receive(...).reply(someVariable), the bot will always respond with the initial value of someVariable, even if it is changed later. "Hello my name is %%bot_name%%"

Command Menu Template

You can use bot.createCommandMenu() to generate menu string for your command list. You can edit the template in the bot-config.json file. See the default template

You can pass in extraCommands as the argument. It is an array of commands ({name, description, category}) that you want to show in the result.

Mentioning

If the message text contains the pattern @phonenumber (ex:@62821234567) it will be automatically converted to a mention.

Baileys' Objects

In case you want to do your own functionality

  1. bot.getSocket() : The sock/socket/client/conn object that is typically used in baileys
  2. message.getBaileysMessage() : Returns original baileys message object. See above in the section about message object

Readme

Keywords

Package Sidebar

Install

npm i @aidulcandra/simple-wa-bot

Weekly Downloads

247

Version

26.6.2

License

ISC

Unpacked Size

98.4 kB

Total Files

5

Last publish

Collaborators

  • aidulcandra