Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Warning: ini hanyalah repo baileys yang sudah ter update & fix jika ada problem. memudahkan bagi pemula jika ada pull req di repo utama yang belum di acc
Note: kalau ada problem atau masalah, tanya2 ke grup dibawah ini
GRUP INFO BAILEYS: KLIK DISINI
silahkan tambahkan ini pada kode config connection anda. jika hydrate ga work, tambahin viewOnce: true setelah footer. kode lengkapnya cek contoh hydrate dibawah
const sock = makeWASocket({
// can provide additional config here
...
printQRInTerminal: true,
patchMessageBeforeSending: (message) => {
const requiresPatch = !!(
message.buttonsMessage
|| message.templateMessage
|| message.listMessage
);
if (requiresPatch) {
message = {
viewOnceMessage: {
message: {
messageContextInfo: {
deviceListMetadataVersion: 2,
deviceListMetadata: {},
},
...message,
},
},
};
}
return message;
},
})
edit package.json anda
ubah menjadi "@adiwajshing/baileys": "github:amiruldev20/Baileys"
jika ingin versi npm
ubah menjadi "@adiwajshing/baileys": "npm:baileys@^version"
// pesan teks
sock.sendMessage(id, {
text: "Hello, i'm Amirul Dev"
})
// pesan teks reply
sock.sendMessage(id, {
text: "Hello, i'm Amirul Dev"
}, { quoted: message })
// pesan tag
sock.sendMessage(id, {
text: `Hello @6285157489446`,
mentions: ["6285157489446@s.whatsapp.net"]
})
// pesan lokasi
sock.sendMessage(id, {
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221
}
})
// pesan kontak
const vcard = 'BEGIN:VCARD\n' // metadata kontak
+ 'VERSION:3.0\n' // versi
+ 'FN:Amirul Dev\n' // nama
+ 'ORG:Dikode Team;\n' // organisasi
+ 'TEL;type=CELL;type=VOICE;waid=6285157489446:+62 851-5748-9446\n' // id wa & nomor hp
+ 'END:VCARD'
sock.sendMessage(id, {
contacts: {
displayName: 'Developer',
contacts: [{ vcard }]
}
}
)
// pesan button (kalau ga work, pastikan sudah ngikutin tutor diatas. jika tetap tidak fungsi, silahkan lapor ke grup)
const buttons = [
{buttonId: 'id1', buttonText: {displayText: 'Button 1'}, type: 1},
{buttonId: 'id2', buttonText: {displayText: 'Button 2'}, type: 1},
{buttonId: 'id3', buttonText: {displayText: 'Button 3'}, type: 1}
]
const buttonMessage = {
text: "Hi it's button message",
footer: 'Hello World',
buttons: buttons,
headerType: 1
}
sock.sendMessage(id, buttonMessage)
// pesan hydrate (kalau ga work, pastikan sudah ngikutin tutor diatas. jika tetap tidak fungsi, silahkan lapor ke grup)
const templateButtons = [
{index: 1, urlButton: {displayText: '⭐ Star Baileys on GitHub!', url: 'https://github.com/amiruldev20/Baileys'}},
{index: 2, callButton: {displayText: 'Call me!', phoneNumber: '+6285157489446'}},
{index: 3, quickReplyButton: {displayText: 'This is a reply, just like normal buttons!', id: 'id-like-buttons-message'}},
]
const templateMessage = {
text: "Hi it's a template message",
footer: 'Hello World',
viewOnce: true,
templateButtons: templateButtons
}
sock.sendMessage(id, templateMessage)
// pesan list
const 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"}
]
},
]
const listMessage = {
text: "This is a list",
footer: "nice footer, link: https://google.com",
title: "Amazing boldfaced list title",
buttonText: "Required, text on the button to view the list",
sections
}
sock.sendMessage(id, listMessage)
// kirim reaksi
const reactionMessage = {
react: {
text: "💖", // reaksi
key: message.key // key pesan
}
}
sock.sendMessage(id, reactionMessage)
// kirim pesan media (video,sticker,image)
sock.sendMessage(id, {
tye: buffer, // type bisa anda ubah video,sticker atau image
caption: 'Hello world',
gifPlayback: true // true jika ingin mengirim video tipe gif
})
// kirim pesan audio
sock.sendMessage(id, {
audio: {
url:"./media/audio.mp3"
}, {
mimetype: 'audio/mp4'
{
// send an audio file
await sock.sendMessage(
id,
{ audio: { url: "./Media/audio.mp3" }, mimetype: 'audio/mp4' }
{ url: "Media/audio.mp3" }, // can send mp3, mp4, & ogg
)
// send a buttons message with image header!
const buttons = [
{buttonId: 'id1', buttonText: {displayText: 'Button 1'}, type: 1},
{buttonId: 'id2', buttonText: {displayText: 'Button 2'}, type: 1},
{buttonId: 'id3', buttonText: {displayText: 'Button 3'}, type: 1}
]
const buttonMessage = {
image: {url: 'https://example.com/image.jpeg'},
caption: "Hi it's button message",
footer: 'Hello World',
buttons: buttons,
headerType: 4
}
const sendMsg = await sock.sendMessage(id, buttonMessage)
//send a template message with an image **attached**!
const templateButtons = [
{index: 1, urlButton: {displayText: '⭐ Star Baileys on GitHub!', url: 'https://github.com/amiruldev20/Baileys'}},
{index: 2, callButton: {displayText: 'Call me!', phoneNumber: '+1 (234) 5678-901'}},
{index: 3, quickReplyButton: {displayText: 'This is a reply, just like normal buttons!', id: 'id-like-buttons-message'}},
]
const buttonMessage = {
text: "Hi it's a template message",
footer: 'Hello World',
templateButtons: templateButtons,
image: {url: 'https://example.com/image.jpeg'}
}
const sendMsg = await sock.sendMessage(id, templateMessage)
id
is the WhatsApp ID of the person or group you're sending the message to.
[country code][phone number]@s.whatsapp.net
+19999999999@s.whatsapp.net
.123456789-123345@g.us
.[timestamp of creation]@broadcast
.status@broadcast
.jimp
or sharp
as a dependency in your project using yarn add jimp
or yarn add sharp
. Thumbnails for videos can also be generated automatically, though, you need to have ffmpeg
installed on your system.const info: MessageOptions = {
quoted: quotedMessage, // the message you want to quote
contextInfo: { forwardingScore: 2, isForwarded: true }, // some random context info (can show a forwarded message with this too)
timestamp: Date(), // optional, if you want to manually set the timestamp of the message
caption: "hello there!", // (for media messages) the caption to send with the media (cannot be sent with stickers though)
jpegThumbnail: "23GD#4/==", /* (for location & media messages) has to be a base 64 encoded JPEG if you want to send a custom thumb,
or set to null if you don't want to send a thumbnail.
Do not enter this field if you want to automatically generate a thumb
*/
mimetype: Mimetype.pdf, /* (for media messages) specify the type of media (optional for all media types except documents),
import {Mimetype} from 'baileys'
*/
fileName: 'somefile.pdf', // (for media messages) file name for the media
/* will send audio messages as voice notes, if set to true */
ptt: true,
/** Should it send as a disappearing messages.
* By default 'chat' -- which follows the setting of the chat */
ephemeralExpiration: WA_DEFAULT_EPHEMERAL
}
const msg = getMessageFromStore('455@s.whatsapp.net', 'HSJHJWH7323HSJSJ') // implement this on your end
await sock.sendMessage('1234@s.whatsapp.net', { forward: msg }) // WA forward the message!
A set of message keys must be explicitly marked read now. In multi-device, you cannot mark an entire "chat" read as it were with Baileys Web. This means you have to keep track of unread messages.
const key = {
remoteJid: '1234-123@g.us',
id: 'AHASHH123123AHGA', // id of the message you want to read
participant: '912121232@s.whatsapp.net' // the ID of the user that sent the message (undefined for individual chats)
}
// pass to readMessages function
// can pass multiple keys to read multiple messages as well
await sock.readMessages([key])
The message ID is the unique identifier of the message that you are marking as read.
On a WAMessage
, the messageID
can be accessed using messageID = message.key.id
.
await sock.sendPresenceUpdate('available', id)
This lets the person/group with id
know whether you're online, offline, typing etc.
presence
can be one of the following:
type WAPresence = 'unavailable' | 'available' | 'composing' | 'recording' | 'paused'
The presence expires after about 10 seconds.
Note: In the multi-device version of WhatsApp -- if a desktop client is active, WA doesn't send push notifications to the device. If you would like to receive said notifications -- mark your Baileys client offline using sock.sendPresenceUpdate('unavailable')
If you want to save the media you received
import { writeFile } from 'fs/promises'
import { downloadMediaMessage } from 'baileys'
sock.ev.on('messages.upsert', async ({ messages }) => {
const m = messages[0]
if (!m.message) return // if there is no text or media message
const messageType = Object.keys (m.message)[0]// get what type of message it is -- text, image, video
// if the message is an image
if (messageType === 'imageMessage') {
// download the message
const buffer = await downloadMediaMessage(
m,
'buffer',
{ },
{
logger,
// pass this so that baileys can request a reupload of media
// that has been deleted
reuploadRequest: sock.updateMediaMessage
}
)
// save to file
await writeFile('./my-download.jpeg', buffer)
}
}
Note: WhatsApp automatically removes old media from their servers. For the device to access said media -- a re-upload is required by another device that has it. This can be accomplished using:
const updatedMediaMsg = await sock.updateMediaMessage(msg)
const jid = '1234@s.whatsapp.net' // can also be a group
const response = await sock.sendMessage(jid, { text: 'hello!' }) // send a message
// sends a message to delete the given message
// this deletes the message for everyone
await sock.sendMessage(jid, { delete: response.key })
Note: deleting for oneself is supported via chatModify
(next section)
WA uses an encrypted form of communication to send chat/app updates. This has been implemented mostly and you can send the following updates:
Archive a chat
const lastMsgInChat = await getLastMessageInChat('123456@s.whatsapp.net') // implement this on your end
await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, '123456@s.whatsapp.net')
Mute/unmute a chat
// mute for 8 hours
await sock.chatModify({ mute: 8*60*60*1000 }, '123456@s.whatsapp.net', [])
// unmute
await sock.chatModify({ mute: null }, '123456@s.whatsapp.net', [])
Mark a chat read/unread
const lastMsgInChat = await getLastMessageInChat('123456@s.whatsapp.net') // implement this on your end
// mark it unread
await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, '123456@s.whatsapp.net')
Delete a message for me
await sock.chatModify(
{ clear: { messages: [{ id: 'ATWYHDNNWU81732J', fromMe: true, timestamp: "1654823909" }] } },
'123456@s.whatsapp.net',
[]
)
Delete a chat
const lastMsgInChat = await getLastMessageInChat('123456@s.whatsapp.net') // implement this on your end
await sock.chatModify({
delete: true,
lastMessages: [{ key: lastMsgInChat.key, messageTimestamp: lastMsgInChat.messageTimestamp }]
},
'123456@s.whatsapp.net')
Pin/unpin a chat
await sock.chatModify({
pin: true // or `false` to unpin
},
'123456@s.whatsapp.net')
Note: if you mess up one of your updates, WA can log you out of all your devices and you'll have to log in again.
const jid = '1234@s.whatsapp.net' // can also be a group
// turn on disappearing messages
await sock.sendMessage(
jid,
// this is 1 week in seconds -- how long you want messages to appear for
{ disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL }
)
// will send as a disappearing message
await sock.sendMessage(jid, { text: 'hello' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
// turn off disappearing messages
await sock.sendMessage(
jid,
{ disappearingMessagesInChat: false }
)
const id = '123456'
const [result] = await sock.onWhatsApp(id)
if (result.exists) console.log (`${id} exists on WhatsApp, as jid: ${result.jid}`)
const status = await sock.fetchStatus("xyz@s.whatsapp.net")
console.log("status: " + status)
const status = 'Hello World!'
await sock.updateProfileStatus(status)
const name = 'My name'
await sock.updateProfileName(name)
// for low res picture
const ppUrl = await sock.profilePictureUrl("xyz@g.us")
console.log("download profile picture from: " + ppUrl)
// for high res picture
const ppUrl = await sock.profilePictureUrl("xyz@g.us", 'image')
const jid = '111234567890-1594482450@g.us' // can be your own too
await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })
// the presence update is fetched and called here
sock.ev.on('presence-update', json => console.log(json))
// request updates for a chat
await sock.presenceSubscribe("xyz@s.whatsapp.net")
await sock.updateBlockStatus("xyz@s.whatsapp.net", "block") // Block user
await sock.updateBlockStatus("xyz@s.whatsapp.net", "unblock") // Unblock user
const profile = await sock.getBusinessProfile("xyz@s.whatsapp.net")
console.log("business description: " + profile.description + ", category: " + profile.category)
Of course, replace xyz
with an actual ID.
// title & participants
const group = await sock.groupCreate("My Fab Group", ["1234@s.whatsapp.net", "4564@s.whatsapp.net"])
console.log ("created group with id: " + group.gid)
sock.sendMessage(group.id, { text: 'hello there' }) // say hello to everyone on the group
// id & people to add to the group (will throw error if it fails)
const response = await sock.groupParticipantsUpdate(
"abcd-xyz@g.us",
["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"],
"add" // replace this parameter with "remove", "demote" or "promote"
)
await sock.groupUpdateSubject("abcd-xyz@g.us", "New Subject!")
await sock.groupUpdateDescription("abcd-xyz@g.us", "New Description!")
// only allow admins to send messages
await sock.groupSettingUpdate("abcd-xyz@g.us", 'announcement')
// allow everyone to send messages
await sock.groupSettingUpdate("abcd-xyz@g.us", 'not_announcement')
// allow everyone to modify the group's settings -- like display picture etc.
await sock.groupSettingUpdate("abcd-xyz@g.us", 'unlocked')
// only allow admins to modify the group's settings
await sock.groupSettingUpdate("abcd-xyz@g.us", 'locked')
await sock.groupLeave("abcd-xyz@g.us") // (will throw error if it fails)
const code = await sock.groupInviteCode("abcd-xyz@g.us")
console.log("group code: " + code)
const code = await sock.groupRevokeInvite("abcd-xyz@g.us")
console.log("New group code: " + code)
const metadata = await sock.groupMetadata("abcd-xyz@g.us")
console.log(metadata.id + ", title: " + metadata.subject + ", description: " + metadata.desc)
const response = await sock.groupAcceptInvite("xxx")
console.log("joined to: " + response)
Of course, replace xxx
with invitation code.const response = await sock.groupGetInviteInfo("xxx")
console.log("group information: " + response)
const response = await sock.groupAcceptInviteV4("abcd@s.whatsapp.net", groupInviteMessage)
console.log("joined to: " + response)
Of course, replace xxx
with invitation code.Note: messages currently cannot be sent to broadcast lists from the MD version.
12345678@broadcast
const bList = await sock.getBroadcastListInfo("1234@broadcast")
console.log (`list name: ${bList.name}, recps: ${bList.recipients}`)
Baileys is written with custom functionality in mind. Instead of forking the project & re-writing the internals, you can simply write your own extensions.
First, enable the logging of unhandled messages from WhatsApp by setting:
const sock = makeWASocket({
logger: P({ level: 'debug' }),
})
This will enable you to see all sorts of messages WhatsApp sends in the console.
Some examples:
Functionality to track the battery percentage of your phone.
You enable logging and you'll see a message about your battery pop up in the console:
{"level":10,"fromMe":false,"frame":{"tag":"ib","attrs":{"from":"@s.whatsapp.net"},"content":[{"tag":"edge_routing","attrs":{},"content":[{"tag":"routing_info","attrs":{},"content":{"type":"Buffer","data":[8,2,8,5]}}]}]},"msg":"communication"}
The "frame" is what the message received is, it has three components:
tag
-- what this frame is about (eg. message will have "message")attrs
-- a string key-value pair with some metadata (contains ID of the message usually)content
-- the actual data (eg. a message node will have the actual message content in it)You can register a callback for an event using the following:
// for any message with tag 'edge_routing'
sock.ws.on(`CB:edge_routing`, (node: BinaryNode) => { })
// for any message with tag 'edge_routing' and id attribute = abcd
sock.ws.on(`CB:edge_routing,id:abcd`, (node: BinaryNode) => { })
// for any message with tag 'edge_routing', id attribute = abcd & first content node routing_info
sock.ws.on(`CB:edge_routing,id:abcd,routing_info`, (node: BinaryNode) => { })
This library was originally a project for CS-2362 at Ashoka University and is in no way affiliated with WhatsApp. Use at your own discretion. Do not spam people with this.
Also, this repo is now licenced under GPL 3 since it uses libsignal-node
FAQs
WhatsApp API
The npm package baileys receives a total of 2,112 weekly downloads. As such, baileys popularity was classified as popular.
We found that baileys demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.