Got rid of WAClient, deprecated code. Prep for V3

Layered classes based on hierarchy as well.
This commit is contained in:
Adhiraj
2020-08-16 17:51:29 +05:30
parent 1360bef9bb
commit 002d304041
23 changed files with 803 additions and 869 deletions

150
README.md
View File

@@ -21,11 +21,11 @@ To run the example script, download or clone the repo and then type the followin
## Install
Create and cd to your NPM project directory and then in terminal, write:
1. stable: `npm install @adiwajshing/baileys`
2. stabl-ish w quicker fixes & latest features: `npm install github:adiwajshing/baileys`
2. stabl-ish w quicker fixes & latest features: `npm install github:adiwajshing/baileys` (major changes incoming right now)
Then import in your code using:
``` ts
import { WAClient } from '@adiwajshing/baileys'
import { WAConnection } from '@adiwajshing/baileys'
```
## Unit Tests
@@ -36,11 +36,11 @@ Set the phone number you can randomly send messages to in a `.env` file with `TE
## Connecting
``` ts
import { WAClient } from '@adiwajshing/baileys'
import { WAConnection } from '@adiwajshing/baileys'
async function connectToWhatsApp () {
const client = new WAClient()
const [user, chats, contacts] = await client.connect ()
const conn = new WAConnection()
const [user, chats, contacts] = await conn.connect ()
console.log ("oh hello " + user.name + " (" + user.id + ")")
console.log ("you have " + chats.length + " chats")
@@ -61,14 +61,14 @@ connectToWhatsApp ()
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!
If you don't want to wait for WhatsApp to send all your chats while connecting, you can use the following function:
``` ts
import { WAClient } from '@adiwajshing/baileys'
import { WAConnection } from '@adiwajshing/baileys'
async function connectToWhatsApp () {
const client = new WAClient()
const user = await client.connectSlim ()
const conn = new WAConnection()
const user = await conn.connectSlim ()
console.log ("oh hello " + user.name + " (" + user.id + ")")
client.receiveChatsAndContacts () // wait for chats & contacts in the background
conn.receiveChatsAndContacts () // wait for chats & contacts in the background
.then (([chats, contacts]) => {
console.log ("you have " + chats.all().length + " chats and " + contacts.length + " contacts")
})
@@ -91,18 +91,18 @@ So, do the following the first time you connect:
``` ts
import * as fs from 'fs'
const client = new WAClient()
client.connectSlim() // connect first
const conn = new WAConnection()
conn.connectSlim() // connect first
.then (user => {
const creds = client.base64EncodedAuthInfo () // contains all the keys you need to restore a session
const creds = conn.base64EncodedAuthInfo () // contains all the keys you need to restore a session
fs.writeFileSync('./auth_info.json', JSON.stringify(creds, null, '\t')) // save JSON to file
})
```
Then, to restore a session:
``` ts
const client = new WAClient()
client.connectSlim('./auth_info.json') // will load JSON credentials from file
const conn = new WAConnection()
conn.connectSlim('./auth_info.json') // will load JSON credentials from file
.then (user => {
// yay connected without scanning QR
})
@@ -115,8 +115,8 @@ client.connectSlim('./auth_info.json') // will load JSON credentials from file
If you're considering switching from a Chromium/Puppeteer based library, you can use WhatsApp Web's Browser credentials to restore sessions too:
``` ts
client.loadAuthInfoFromBrowser ('./auth_info_browser.json')
client.connectSlim(null, 20*1000) // use loaded credentials & timeout in 20s
conn.loadAuthInfoFromBrowser ('./auth_info_browser.json')
conn.connectSlim(null, 20*1000) // use loaded credentials & timeout in 20s
.then (user => {
// yay! connected using browser keys & without scanning QR
})
@@ -127,25 +127,25 @@ See the browser credentials type [here](/src/WAConnection/Constants.ts).
If you want to do some custom processing with the QR code used to authenticate, you can override the following method:
``` ts
client.onReadyForPhoneAuthentication = ([ref, publicKey, clientID]) => {
conn.onReadyForPhoneAuthentication = ([ref, publicKey, clientID]) => {
const str = ref + ',' + publicKey + ',' + clientID // the QR string
// Now, use 'str' to display in QR UI or send somewhere
}
const user = await client.connect ()
const user = await conn.connect ()
```
If you need to regenerate the QR, you can also do so using:
``` ts
let generateQR: async () => void // call generateQR on some timeout or error
client.onReadyForPhoneAuthentication = ([ref, publicKey, clientID]) => {
conn.onReadyForPhoneAuthentication = ([ref, publicKey, clientID]) => {
generateQR = async () => {
ref = await client.generateNewQRCode () // returns a new ref code to use for QR generation
ref = await conn.generateNewQRCode () // returns a new ref code to use for QR generation
const str = ref + ',' + publicKey + ',' + clientID // the QR string
// re-print str as QR or update in UI or send somewhere
//QR.generate(str, { small: true })
}
}
const user = await client.connect ()
const user = await conn.connect ()
```
## Handling Events
@@ -155,7 +155,7 @@ Implement the following callbacks in your code:
``` ts
import { getNotificationType } from '@adiwajshing/baileys'
// set first param to `true` if you want to receive outgoing messages that may be sent from your phone
client.setOnUnreadMessage (false, (m: WAMessage) => {
conn.setOnUnreadMessage (false, (m: WAMessage) => {
// get what type of notification it is -- message, group add notification etc.
const [notificationType, messageType] = getNotificationType(m)
@@ -165,11 +165,11 @@ Implement the following callbacks in your code:
```
- Called when you recieve an update on someone's presence, they went offline or online
``` ts
client.setOnPresenceUpdate ((json: PresenceUpdate) => console.log(json.id + " presence is " + json.type))
conn.setOnPresenceUpdate ((json: PresenceUpdate) => console.log(json.id + " presence is " + json.type))
```
- Called when your message gets delivered or read
``` ts
client.setOnMessageStatusChange ((json: MessageStatusUpdate) => {
conn.setOnMessageStatusChange ((json: MessageStatusUpdate) => {
let sent = json.to
if (json.participant) // participant exists when the message is from a group
sent += " ("+json.participant+")" // mention as the one sent to
@@ -179,7 +179,7 @@ Implement the following callbacks in your code:
```
- Called when the connection gets disconnected (either the server loses internet, the phone gets unpaired, or the connection is taken over from somewhere)
``` ts
client.setOnUnexpectedDisconnect (reason => console.log ("disconnected unexpectedly: " + reason) )
conn.setOnUnexpectedDisconnect (reason => console.log ("disconnected unexpectedly: " + reason) )
```
## Sending Messages
@@ -189,9 +189,9 @@ import { MessageType, MessageOptions, Mimetype } from '@adiwajshing/baileys'
const id = 'abcd@s.whatsapp.net' // the WhatsApp ID
// send a simple text!
client.sendMessage (id, 'oh hello there', MessageType.text)
conn.sendMessage (id, 'oh hello there', MessageType.text)
// send a location!
client.sendMessage(id, {degreeslatitude: 24.121231, degreesLongitude: 55.1121221}, MessageType.location)
conn.sendMessage(id, {degreeslatitude: 24.121231, degreesLongitude: 55.1121221}, MessageType.location)
// send a contact!
const vcard = 'BEGIN:VCARD\n' // metadata of the contact card
+ 'VERSION:3.0\n'
@@ -199,11 +199,11 @@ const vcard = 'BEGIN:VCARD\n' // metadata of the contact card
+ 'ORG:Ashoka Uni;\n' // the organization of the contact
+ 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n' // WhatsApp ID + phone number
+ 'END:VCARD'
client.sendMessage(id, {displayname: "Jeff", vcard: vcard}, MessageType.contact)
conn.sendMessage(id, {displayname: "Jeff", vcard: vcard}, MessageType.contact)
// send a gif
const buffer = fs.readFileSync("Media/ma_gif.mp4") // load some gif
const options: MessageOptions = {mimetype: Mimetype.gif, caption: "hello!"} // some metadata & caption
client.sendMessage(id, buffer, MessageType.video, options)
conn.sendMessage(id, buffer, MessageType.video, options)
```
To note:
- `id` is the WhatsApp ID of the person or group you're sending the message to.
@@ -233,9 +233,9 @@ To note:
## Forwarding Messages
``` ts
const messages = await client.loadConversation ('1234@s.whatsapp.net', 1)
const messages = await conn.loadConversation ('1234@s.whatsapp.net', 1)
const message = messages[0] // get the last message from this conversation
await client.forwardMessage ('455@s.whatsapp.net', message) // WA forward the message!
await conn.forwardMessage ('455@s.whatsapp.net', message) // WA forward the message!
```
## Reading Messages
@@ -243,10 +243,10 @@ await client.forwardMessage ('455@s.whatsapp.net', message) // WA forward the me
const id = '1234-123@g.us'
const messageID = 'AHASHH123123AHGA' // id of the message you want to read
await client.sendReadReceipt(id, messageID) // mark as read
await client.sendReadReceipt (id) // mark all messages in chat as read
await conn.sendReadReceipt(id, messageID) // mark as read
await conn.sendReadReceipt (id) // mark all messages in chat as read
await client.sendReadReceipt(id, null, 'unread') // mark the chat as unread
await conn.sendReadReceipt(id, null, 'unread') // mark the chat as unread
```
- `id` is in the same format as mentioned earlier.
@@ -258,7 +258,7 @@ await client.sendReadReceipt(id, null, 'unread') // mark the chat as unread
``` ts
import { Presence } from '@adiwajshing/baileys'
client.updatePresence(id, Presence.available)
conn.updatePresence(id, Presence.available)
```
This lets the person/group with ``` id ``` know whether you're online, offline, typing etc. where ``` presence ``` can be one of the following:
``` ts
@@ -275,15 +275,15 @@ export enum Presence {
If you want to save the media you received
``` ts
import { MessageType, extensionForMediaMessage } from '@adiwajshing/baileys'
client.setOnUnreadMessage (false, async m => {
conn.setOnUnreadMessage (false, async m => {
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 not a text message
if (messageType !== MessageType.text && messageType !== MessageType.extendedText) {
const buffer = await client.downloadMediaMessage(m) // to decrypt & use as a buffer
const buffer = await conn.downloadMediaMessage(m) // to decrypt & use as a buffer
const savedFilename = await client.downloadAndSaveMediaMessage (m) // to decrypt & save to file
const savedFilename = await conn.downloadAndSaveMediaMessage (m) // to decrypt & save to file
console.log(m.key.remoteJid + " sent media, saved at: " + savedFilename)
}
}
@@ -293,29 +293,29 @@ client.setOnUnreadMessage (false, async m => {
``` ts
const jid = '1234@s.whatsapp.net' // can also be a group
const response = await client.sendMessage (jid, 'hello!', MessageType.text) // send a message
const response = await conn.sendMessage (jid, 'hello!', MessageType.text) // send a message
await client.deleteMessage (jid, {id: response.messageID, remoteJid: jid, fromMe: true}) // will delete the sent message for everyone!
await client.clearMessage (jid, {id: response.messageID, remoteJid: jid, fromMe: true}) // will delete the sent message for only you!
await conn.deleteMessage (jid, {id: response.messageID, remoteJid: jid, fromMe: true}) // will delete the sent message for everyone!
await conn.clearMessage (jid, {id: response.messageID, remoteJid: jid, fromMe: true}) // will delete the sent message for only you!
```
## Modifying Chats
``` ts
const jid = '1234@s.whatsapp.net' // can also be a group
await client.modifyChat (jid, ChatModification.archive) // archive chat
await client.modifyChat (jid, ChatModification.unarchive) // unarchive chat
await conn.modifyChat (jid, ChatModification.archive) // archive chat
await conn.modifyChat (jid, ChatModification.unarchive) // unarchive chat
const response = await client.modifyChat (jid, ChatModification.pin) // pin the chat
await client.modifyChat (jid, ChatModification.unpin, {stamp: response.stamp})
const response = await conn.modifyChat (jid, ChatModification.pin) // pin the chat
await conn.modifyChat (jid, ChatModification.unpin, {stamp: response.stamp})
const mutedate = new Date (new Date().getTime() + 8*60*60*1000) // mute for 8 hours in the future
await client.modifyChat (jid, ChatModification.mute, {stamp: mutedate}) // mute
await conn.modifyChat (jid, ChatModification.mute, {stamp: mutedate}) // mute
setTimeout (() => {
client.modifyChat (jid, ChatModification.unmute, {stamp: mutedate})
conn.modifyChat (jid, ChatModification.unmute, {stamp: mutedate})
}, 5000) // unmute after 5 seconds
await client.deleteChat (jid) // will delete the chat (can be a group or broadcast list)
await conn.deleteChat (jid) // will delete the chat (can be a group or broadcast list)
```
**Note:** to unmute or unpin a chat, one must pass the timestamp of the pinning or muting. This is returned by the pin & mute functions. This is also available in the `WAChat` objects of the respective chats, as a `mute` or `pin` property.
@@ -325,48 +325,48 @@ await client.deleteChat (jid) // will delete the chat (can be a group or broadca
- To check if a given ID is on WhatsApp
``` ts
const id = 'xyz@s.whatsapp.net'
const exists = await client.isOnWhatsApp (id)
const exists = await conn.isOnWhatsApp (id)
console.log (`${id} ${exists ? " exists " : " does not exist"} on WhatsApp`)
```
- To query chat history on a group or with someone
``` ts
// query the last 25 messages (replace 25 with the number of messages you want to query)
const messages = await client.loadConversation ("xyz-abc@g.us", 25)
const messages = await conn.loadConversation ("xyz-abc@g.us", 25)
console.log("got back " + messages.length + " messages")
```
You can also load the entire conversation history if you want
``` ts
await client.loadEntireConversation ("xyz@c.us", message => console.log("Loaded message with ID: " + message.key.id))
await conn.loadEntireConversation ("xyz@c.us", message => console.log("Loaded message with ID: " + message.key.id))
console.log("queried all messages") // promise resolves once all messages are retreived
```
- To get the status of some person
``` ts
const status = await client.getStatus ("xyz@c.us") // leave empty to get your own status
const status = await conn.getStatus ("xyz@c.us") // leave empty to get your own status
console.log("status: " + status)
```
- To get the display picture of some person/group
``` ts
const ppUrl = await client.getProfilePicture ("xyz@g.us") // leave empty to get your own
const ppUrl = await conn.getProfilePicture ("xyz@g.us") // leave empty to get your own
console.log("download profile picture from: " + ppUrl)
```
- To change your display picture or a group's
``` ts
const jid = '111234567890-1594482450@g.us' // can be your own too
const img = fs.readFileSync ('new-profile-picture.jpeg') // can be PNG also
await client.updateProfilePicture (jid, newPP)
await conn.updateProfilePicture (jid, newPP)
```
- To get someone's presence (if they're typing, online)
``` ts
// the presence update is fetched and called here
client.setOnPresenceUpdate (json => console.log(json.id + " presence is " + json.type))
await client.requestPresenceUpdate ("xyz@c.us") // request the update
conn.setOnPresenceUpdate (json => console.log(json.id + " presence is " + json.type))
await conn.requestPresenceUpdate ("xyz@c.us") // request the update
```
- To search through messages
``` ts
const response = await client.searchMessages ('so cool', null, 25, 1) // search in all chats
const response = await conn.searchMessages ('so cool', null, 25, 1) // search in all chats
console.log (`got ${response.messages.length} messages in search`)
const response2 = await client.searchMessages ('so cool', '1234@c.us', 25, 1) // search in given chat
const response2 = await conn.searchMessages ('so cool', '1234@c.us', 25, 1) // search in given chat
```
Of course, replace ``` xyz ``` with an actual ID.
Append ``` @s.whatsapp.net ``` for individuals & ``` @g.us ``` for groups.
@@ -375,47 +375,47 @@ Append ``` @s.whatsapp.net ``` for individuals & ``` @g.us ``` for groups.
- To create a group
``` ts
// title & participants
const group = await client.groupCreate ("My Fab Group", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"])
const group = await conn.groupCreate ("My Fab Group", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"])
console.log ("created group with id: " + group.gid)
client.sendTextMessage(group.gid, "hello everyone") // say hello to everyone on the group
conn.sendMessage(group.gid, "hello everyone", MessageType.extendedText) // say hello to everyone on the group
```
- To add people to a group
``` ts
// id & people to add to the group (will throw error if it fails)
const response = await client.groupAdd ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"])
const response = await conn.groupAdd ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"])
```
- To make/demote admins on a group
``` ts
// id & people to make admin (will throw error if it fails)
await client.groupMakeAdmin ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"])
await client.groupDemoteAdmin ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"]) // demote admins
await conn.groupMakeAdmin ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"])
await conn.groupDemoteAdmin ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"]) // demote admins
```
- To change group settings
``` ts
import { GroupSettingChange } from '@adiwajshing/baileys'
// only allow admins to send messages
await client.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.messageSend, true)
await conn.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.messageSend, true)
// allow everyone to modify the group's settings -- like display picture etc.
await client.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.settingChange, false)
await conn.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.settingChange, false)
// only allow admins to modify the group's settings
await client.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.settingChange, true)
await conn.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.settingChange, true)
```
- To leave a group
``` ts
await client.groupLeave ("abcd-xyz@g.us") // (will throw error if it fails)
await conn.groupLeave ("abcd-xyz@g.us") // (will throw error if it fails)
```
- To get the invite code for a group
``` ts
const code = await client.groupInviteCode ("abcd-xyz@g.us")
const code = await conn.groupInviteCode ("abcd-xyz@g.us")
console.log("group code: " + code)
```
- To query the metadata of a group
``` ts
const metadata = await client.groupMetadata ("abcd-xyz@g.us")
const metadata = await conn.groupMetadata ("abcd-xyz@g.us")
console.log(json.id + ", title: " + json.subject + ", description: " + json.desc)
// Or if you've left the group -- call this
const metadata2 = await client.groupMetadataMinimal ("abcd-xyz@g.us")
const metadata2 = await conn.groupMetadataMinimal ("abcd-xyz@g.us")
```
## Broadcast Lists & Stories
@@ -425,7 +425,7 @@ Append ``` @s.whatsapp.net ``` for individuals & ``` @g.us ``` for groups.
- Broadcast IDs are in the format `12345678@broadcast`
- To query a broadcast list's recipients & name:
``` ts
const bList = await client.getBroadcastListInfo ("1234@broadcast")
const bList = await conn.getBroadcastListInfo ("1234@broadcast")
console.log (`list name: ${bList.name}, recps: ${bList.recipients}`)
```
@@ -434,7 +434,7 @@ Baileys is written, keeping in mind, that you may require other custom functiona
First, enable the logging of unhandled messages from WhatsApp by setting
``` ts
client.logLevel = MessageLogLevel.unhandled // set to MessageLogLevel.all to see all messages received
conn.logLevel = MessageLogLevel.unhandled // set to MessageLogLevel.all to see all messages received
```
This will enable you to see all sorts of messages WhatsApp sends in the console. Some examples:
@@ -450,7 +450,7 @@ This will enable you to see all sorts of messages WhatsApp sends in the console.
Hence, you can register a callback for an event using the following:
``` ts
client.registerCallback (["action", null, "battery"], json => {
conn.registerCallback (["action", null, "battery"], json => {
const batteryLevelStr = json[2][0][1].value
const batterylevel = parseInt (batteryLevelStr)
console.log ("battery level: " + batterylevel + "%")
@@ -470,9 +470,9 @@ This will enable you to see all sorts of messages WhatsApp sends in the console.
Following this, one can implement the following callback:
``` ts
client.registerCallback (["Conn", "pushname"], json => {
conn.registerCallback (["Conn", "pushname"], json => {
const pushname = json[1].pushname
client.userMetaData.name = pushname // update on client too
conn.userMetaData.name = pushname // update on client too
console.log ("Name updated: " + pushname)
})
```