separated out connect & receiving chats

This commit is contained in:
Adhiraj Singh
2020-06-13 12:43:00 +05:30
parent 7d9fa7a6d1
commit f04fe71530
3 changed files with 70 additions and 58 deletions

View File

@@ -9,9 +9,20 @@ module.exports = {
* Connect to WhatsAppWeb * Connect to WhatsAppWeb
* @param {Object} [authInfo] credentials to log back in * @param {Object} [authInfo] credentials to log back in
* @param {number} [timeoutMs] timeout after which the connect will fail, set to null for an infinite timeout * @param {number} [timeoutMs] timeout after which the connect will fail, set to null for an infinite timeout
* @return {promise<[object, any[], any[], any[]]>} returns [userMetaData, chats, contacts, unreadMessages] * @return {[object, object[], object[], object[]]} returns [userMetaData, chats, contacts, unreadMessages]
*/ */
connect: function (authInfo, timeoutMs) { connect: async function (authInfo, timeoutMs) {
const userInfo = await this.connectSlim (authInfo, timeoutMs)
const chats = await this.receiveChatsAndContacts (authInfo, timeoutMs)
return [userInfo, ...chats]
},
/**
* Connect to WhatsAppWeb, resolves without waiting for chats & contacts
* @param {Object} [authInfo] credentials to log back in
* @param {number} [timeoutMs] timeout after which the connect will fail, set to null for an infinite timeout
* @return {Promise<Object>} returns [userMetaData, chats, contacts, unreadMessages]
*/
connectSlim: function (authInfo, timeoutMs) {
// set authentication credentials if required // set authentication credentials if required
if (authInfo) { if (authInfo) {
this.authInfo = Object.assign ({}, authInfo) // copy credentials this.authInfo = Object.assign ({}, authInfo) // copy credentials
@@ -26,7 +37,7 @@ module.exports = {
let promise = new Promise ( (resolve, reject) => { let promise = new Promise ( (resolve, reject) => {
this.conn.on('open', () => { this.conn.on('open', () => {
this.conn.on('message', (m) => this.onMessageRecieved(m)) // in WhatsAppWeb.Recv.js this.conn.on('message', m => this.onMessageRecieved(m)) // in WhatsAppWeb.Recv.js
this.beginAuthentication ().then (resolve).catch (reject) this.beginAuthentication ().then (resolve).catch (reject)
}) })
this.conn.on('error', error => { // if there was an error in the WebSocket this.conn.on('error', error => { // if there was an error in the WebSocket
@@ -35,12 +46,10 @@ module.exports = {
}) })
}) })
promise = timeoutMs ? Utils.promiseTimeout (timeoutMs, promise) : promise promise = timeoutMs ? Utils.promiseTimeout (timeoutMs, promise) : promise
return promise.catch (err => { return promise.catch (err => {this.close (); throw err;})
this.close ()
throw err
})
}, },
/** once a connection has been successfully established /**
* Once a connection has been successfully established
* @private * @private
* @return {promise<object[]>} * @return {promise<object[]>}
*/ */
@@ -50,12 +59,7 @@ module.exports = {
if (!this.authInfo.clientID) { // if no auth info is present, that is, a new session has to be established if (!this.authInfo.clientID) { // if no auth info is present, that is, a new session has to be established
this.authInfo = { clientID: Utils.generateClientID() } // generate a client ID this.authInfo = { clientID: Utils.generateClientID() } // generate a client ID
} }
let chats = []
let contacts = []
let unreadMessages = []
let unreadMap = {}
const data = ["admin", "init", this.version, this.browserDescriptions, this.authInfo.clientID, true] const data = ["admin", "init", this.version, this.browserDescriptions, this.authInfo.clientID, true]
return this.query(data) return this.query(data)
.then (([json, _]) => { .then (([json, _]) => {
@@ -102,52 +106,60 @@ module.exports = {
this.startKeepAliveRequest() // start sending keep alive requests (keeps the WebSocket alive & updates our last seen) this.startKeepAliveRequest() // start sending keep alive requests (keeps the WebSocket alive & updates our last seen)
}) // validate the connection }) // validate the connection
.then (() => { .then (() => {
this.log ("waiting for chats & contacts") // wait for the message with chats this.log("connected successfully")
const waitForConvos = () => new Promise ((resolve, _) => { return this.userMetaData
const chatUpdate = (json) => { })
const isLast = json[1].last },
json = json[2] /**
if (json) { * Sets up callbacks to receive chats, contacts & unread messages.
for (var k = json.length-1;k >= 0;k--) { * Must be called immediately after connect
const message = json[k][2] * @returns {[ object[], object[], object[] ]} - [chats, contacts, unreadMessages]
const jid = message.key.remoteJid.replace ("@s.whatsapp.net", "@c.us") */
if (!message.key.fromMe && unreadMap[jid] > 0) { // only forward if the message is from the sender receiveChatsAndContacts: function () {
unreadMessages.push (message) let chats = []
unreadMap[jid] -= 1 // reduce let contacts = []
} let unreadMessages = []
let unreadMap = {}
this.log ("waiting for chats & contacts") // wait for the message with chats
const waitForConvos = () => new Promise ((resolve, _) => {
const chatUpdate = (json) => {
const isLast = json[1].last
json = json[2]
if (json) {
for (var k = json.length-1;k >= 0;k--) {
const message = json[k][2]
const jid = message.key.remoteJid.replace ("@s.whatsapp.net", "@c.us")
if (!message.key.fromMe && unreadMap[jid] > 0) { // only forward if the message is from the sender
unreadMessages.push (message)
unreadMap[jid] -= 1 // reduce
} }
} }
if (isLast) {
// de-register the callbacks, so that they don't get called again
this.deregisterCallback (["action", "add:last"])
this.deregisterCallback (["action", "add:before"])
this.deregisterCallback (["action", "add:unread"])
resolve ()
}
} }
// wait for actual messages to load, "last" is the most recent message, "before" contains prior messages if (isLast) {
this.registerCallback (["action", "add:last"], chatUpdate) // de-register the callbacks, so that they don't get called again
this.registerCallback (["action", "add:before"], chatUpdate) this.deregisterCallback (["action", "add:last"])
this.registerCallback (["action", "add:unread"], chatUpdate) this.deregisterCallback (["action", "add:before"])
}) this.deregisterCallback (["action", "add:unread"])
const waitForChats = this.registerCallbackOneTime (["response", "type:chat"]).then (json => { resolve ()
chats = json[2] // chats data (log json to see what it looks like)
chats.forEach (chat => unreadMap [chat[1].jid] = chat[1].count) // store the number of unread messages for each sender
if (chats && chats.length > 0) {
return waitForConvos ()
} }
}) }
const waitForContacts = this.registerCallbackOneTime (["response", "type:contacts"]) // wait for actual messages to load, "last" is the most recent message, "before" contains prior messages
.then (json => contacts = json[2]) this.registerCallback (["action", "add:last"], chatUpdate)
// wait for the chats & contacts to load this.registerCallback (["action", "add:before"], chatUpdate)
return Promise.all ([waitForChats, waitForContacts]) this.registerCallback (["action", "add:unread"], chatUpdate)
}) })
.then (() => { const waitForChats = this.registerCallbackOneTime (["response", "type:chat"]).then (json => {
// now we're successfully connected chats = json[2] // chats data (log json to see what it looks like)
this.log("connected successfully") chats.forEach (chat => unreadMap [chat[1].jid] = chat[1].count) // store the number of unread messages for each sender
// resolve the promise if (chats && chats.length > 0) {
return [this.userMetaData, chats, contacts, unreadMessages] return waitForConvos ()
}
}) })
const waitForContacts = this.registerCallbackOneTime (["response", "type:contacts"])
.then (json => contacts = json[2])
// wait for the chats & contacts to load
return Promise.all ([waitForChats, waitForContacts]).then (() => [chats, contacts, unreadMessages])
}, },
/** /**
* Once the QR code is scanned and we can validate our connection, or we resolved the challenge when logging back in * Once the QR code is scanned and we can validate our connection, or we resolved the challenge when logging back in

View File

@@ -178,9 +178,7 @@ class WhatsAppWeb {
QR.generate(str, {small: true}) QR.generate(str, {small: true})
} }
log (text) { log (text) { console.log (`[Baileys] ${text}`) }
console.log (`[Baileys] ${text}"`)
}
} }
/* Import the rest of the code */ /* Import the rest of the code */
@@ -203,6 +201,8 @@ WhatsAppWeb.prototype.decodeMediaMessage = recv.decodeMediaMessage
const session = require("./WhatsAppWeb.Session") const session = require("./WhatsAppWeb.Session")
WhatsAppWeb.prototype.connect = session.connect WhatsAppWeb.prototype.connect = session.connect
WhatsAppWeb.prototype.connectSlim = session.connectSlim
WhatsAppWeb.prototype.receiveChatsAndContacts = session.receiveChatsAndContacts
WhatsAppWeb.prototype.beginAuthentication = session.beginAuthentication WhatsAppWeb.prototype.beginAuthentication = session.beginAuthentication
WhatsAppWeb.prototype.validateNewConnection = session.validateNewConnection WhatsAppWeb.prototype.validateNewConnection = session.validateNewConnection
WhatsAppWeb.prototype.respondToChallenge = session.respondToChallenge WhatsAppWeb.prototype.respondToChallenge = session.respondToChallenge

View File

@@ -11,7 +11,7 @@ try {
authInfo = JSON.parse(file) authInfo = JSON.parse(file)
} catch { } } catch { }
client.connect (authInfo, 30*1000) // connect or timeout in 30 seconds client.connect (authInfo, 20*1000) // connect or timeout in 20 seconds
.then (([user, chats, contacts, unread]) => { .then (([user, chats, contacts, unread]) => {
console.log ("oh hello " + user.name + " (" + user.id + ")") console.log ("oh hello " + user.name + " (" + user.id + ")")
console.log ("you have " + unread.length + " unread messages") console.log ("you have " + unread.length + " unread messages")