Cleaner code. Remove credentials-updated & connection-validated as they became obsolete

`credentials-updated` & `connection-validated` became obsolete as they are equivalent to `open`
This commit is contained in:
Adhiraj Singh
2021-01-04 17:07:51 +05:30
parent 6cc5a910f7
commit efe6bf1dd3
6 changed files with 59 additions and 81 deletions

View File

@@ -9,7 +9,6 @@ import {
ReconnectMode, ReconnectMode,
ProxyAgent, ProxyAgent,
waChatKey, waChatKey,
delay,
} from '../src/WAConnection/WAConnection' } from '../src/WAConnection/WAConnection'
import * as fs from 'fs' import * as fs from 'fs'
@@ -20,13 +19,6 @@ async function example() {
// attempt to reconnect at most 10 times in a row // attempt to reconnect at most 10 times in a row
conn.connectOptions.maxRetries = 10 conn.connectOptions.maxRetries = 10
conn.chatOrderingKey = waChatKey(true) // order chats such that pinned chats are on top conn.chatOrderingKey = waChatKey(true) // order chats such that pinned chats are on top
conn.on ('credentials-updated', () => {
// save credentials whenever updated
console.log (`credentials updated`)
const authInfo = conn.base64EncodedAuthInfo() // get all the auth info we need to restore this session
fs.writeFileSync('./auth_info.json', JSON.stringify(authInfo, null, '\t')) // save this info to a file
})
conn.on('chats-received', ({ hasNewChats }) => { conn.on('chats-received', ({ hasNewChats }) => {
console.log(`you have ${conn.chats.length} chats, new chats available: ${hasNewChats}`) console.log(`you have ${conn.chats.length} chats, new chats available: ${hasNewChats}`)
}) })
@@ -41,6 +33,9 @@ async function example() {
// uncomment the following line to proxy the connection; some random proxy I got off of: https://proxyscrape.com/free-proxy-list // uncomment the following line to proxy the connection; some random proxy I got off of: https://proxyscrape.com/free-proxy-list
//conn.connectOptions.agent = ProxyAgent ('http://1.0.180.120:8080') //conn.connectOptions.agent = ProxyAgent ('http://1.0.180.120:8080')
await conn.connect() await conn.connect()
// credentials are updated on every connect
const authInfo = conn.base64EncodedAuthInfo() // get all the auth info we need to restore this session
fs.writeFileSync('./auth_info.json', JSON.stringify(authInfo, null, '\t')) // save this info to a file
console.log('oh hello ' + conn.user.name + ' (' + conn.user.jid + ')') console.log('oh hello ' + conn.user.name + ' (' + conn.user.jid + ')')

View File

@@ -100,16 +100,20 @@ export class WAConnection extends EventEmitter {
return null return null
} }
async unexpectedDisconnect (error: DisconnectReason) { async unexpectedDisconnect (error: DisconnectReason) {
const willReconnect = if (this.state === 'open') {
const willReconnect =
(this.autoReconnect === ReconnectMode.onAllErrors || (this.autoReconnect === ReconnectMode.onAllErrors ||
(this.autoReconnect === ReconnectMode.onConnectionLost && error !== DisconnectReason.replaced)) && (this.autoReconnect === ReconnectMode.onConnectionLost && error !== DisconnectReason.replaced)) &&
error !== DisconnectReason.invalidSession // do not reconnect if credentials have been invalidated error !== DisconnectReason.invalidSession // do not reconnect if credentials have been invalidated
this.closeInternal(error, willReconnect) this.closeInternal(error, willReconnect)
willReconnect && ( willReconnect && (
this.connect () this.connect()
.catch(err => {}) // prevent unhandled exeception .catch(err => {}) // prevent unhandled exeception
) )
} else {
this.endConnection(error)
}
} }
/** /**
* base 64 encode the authentication credentials and return them * base 64 encode the authentication credentials and return them
@@ -313,7 +317,7 @@ export class WAConnection extends EventEmitter {
protected startDebouncedTimeout () { protected startDebouncedTimeout () {
this.stopDebouncedTimeout () this.stopDebouncedTimeout ()
this.debounceTimeout = setTimeout ( this.debounceTimeout = setTimeout (
() => this.emit('ws-close', { reason: DisconnectReason.timedOut }), () => this.endConnection(DisconnectReason.timedOut),
this.connectOptions.maxIdleTimeMs this.connectOptions.maxIdleTimeMs
) )
} }
@@ -394,11 +398,11 @@ export class WAConnection extends EventEmitter {
this.lastDisconnectReason = reason this.lastDisconnectReason = reason
this.lastDisconnectTime = new Date () this.lastDisconnectTime = new Date ()
this.endConnection () this.endConnection(reason)
// reconnecting if the timeout is active for the reconnect loop // reconnecting if the timeout is active for the reconnect loop
this.emit ('close', { reason, isReconnecting }) this.emit ('close', { reason, isReconnecting })
} }
protected endConnection () { protected endConnection (reason: DisconnectReason) {
this.conn?.removeAllListeners ('close') this.conn?.removeAllListeners ('close')
this.conn?.removeAllListeners ('error') this.conn?.removeAllListeners ('error')
this.conn?.removeAllListeners ('open') this.conn?.removeAllListeners ('open')
@@ -410,7 +414,7 @@ export class WAConnection extends EventEmitter {
this.phoneCheckListeners = 0 this.phoneCheckListeners = 0
this.clearPhoneCheckInterval () this.clearPhoneCheckInterval ()
this.emit ('ws-close', { reason: DisconnectReason.close }) this.emit ('ws-close', { reason })
try { try {
this.conn?.close() this.conn?.close()

View File

@@ -87,33 +87,21 @@ export class WAConnection extends Base {
response = await this.waitForMessage('s2', true) response = await this.waitForMessage('s2', true)
} }
const newUser = this.validateNewConnection(response[1]) // validate the connection const {user, auth} = this.validateNewConnection(response[1]) // validate the connection
if (newUser.jid !== this.user?.jid) { if (user.jid !== this.user?.jid) {
isNewUser = true isNewUser = true
// clear out old data // clear out old data
this.chats.clear() this.chats.clear()
this.contacts = {} this.contacts = {}
} }
this.user = newUser this.user = user
this.logger.info('validated connection successfully') this.logger.info('validated connection successfully')
this.emit ('connection-validated', this.user)
if (this.loadProfilePicturesForChatsAutomatically) {
const response = await this.query({
json: ['query', 'ProfilePicThumb', this.user.jid],
waitForOpen: false,
expect200: false,
requiresPhoneConnection: false,
startDebouncedTimeout: true
})
this.user.imgUrl = response?.eurl || ''
}
this.sendPostConnectQueries () this.sendPostConnectQueries ()
this.logger.debug('sent init queries') this.logger.debug('sent init queries')
return { isNewUser } return { user, auth, isNewUser }
} }
/** /**
* Send the same queries WA Web sends after connect * Send the same queries WA Web sends after connect
@@ -149,25 +137,22 @@ export class WAConnection extends Base {
private validateNewConnection(json) { private validateNewConnection(json) {
// set metadata: one's WhatsApp ID [cc][number]@s.whatsapp.net, name on WhatsApp, info about the phone // set metadata: one's WhatsApp ID [cc][number]@s.whatsapp.net, name on WhatsApp, info about the phone
const onValidationSuccess = () => ({ const onValidationSuccess = () => ({
jid: Utils.whatsappID(json.wid), user: {
name: json.pushname, jid: Utils.whatsappID(json.wid),
phone: json.phone, name: json.pushname,
imgUrl: null phone: json.phone,
}) as WAUser imgUrl: null
} as WAUser,
auth: this.authInfo
})
if (!json.secret) { if (!json.secret) {
let credsChanged = false
// if we didn't get a secret, we don't need it, we're validated // if we didn't get a secret, we don't need it, we're validated
if (json.clientToken && json.clientToken !== this.authInfo.clientToken) { if (json.clientToken && json.clientToken !== this.authInfo.clientToken) {
this.authInfo = { ...this.authInfo, clientToken: json.clientToken } this.authInfo = { ...this.authInfo, clientToken: json.clientToken }
credsChanged = true
} }
if (json.serverToken && json.serverToken !== this.authInfo.serverToken) { if (json.serverToken && json.serverToken !== this.authInfo.serverToken) {
this.authInfo = { ...this.authInfo, serverToken: json.serverToken } this.authInfo = { ...this.authInfo, serverToken: json.serverToken }
credsChanged = true
}
if (credsChanged) {
this.emit ('credentials-updated', this.authInfo)
} }
return onValidationSuccess() return onValidationSuccess()
} }
@@ -208,8 +193,6 @@ export class WAConnection extends Base {
serverToken: json.serverToken, serverToken: json.serverToken,
clientID: this.authInfo.clientID, clientID: this.authInfo.clientID,
} }
this.emit ('credentials-updated', this.authInfo)
return onValidationSuccess() return onValidationSuccess()
} }
/** /**
@@ -238,16 +221,17 @@ export class WAConnection extends Base {
this.logger.debug ('regenerating QR') this.logger.debug ('regenerating QR')
try { try {
const {ref: newRef, ttl} = await this.requestNewQRCodeRef() const {ref: newRef, ttl: newTTL} = await this.requestNewQRCodeRef()
ttl = newTTL
ref = newRef ref = newRef
qrLoop (ttl)
} catch (error) { } catch (error) {
this.logger.warn ({ error }, `error in QR gen`) this.logger.warn ({ error }, `error in QR gen`)
if (error.status === 429) { // too many QR requests if (error.status === 429) { // too many QR requests
this.emit ('ws-close', { reason: error.message }) this.endConnection(error.message)
return
} }
} }
qrLoop (ttl)
}, ttl || 20_000) // default is 20s, on the off-chance ttl is not present }, ttl || 20_000) // default is 20s, on the off-chance ttl is not present
} }
qrLoop (ttl) qrLoop (ttl)

View File

@@ -23,12 +23,12 @@ export class WAConnection extends Base {
let tries = 0 let tries = 0
let lastConnect = this.lastDisconnectTime let lastConnect = this.lastDisconnectTime
let updates: any let result: WAOpenResult
while (this.state === 'connecting') { while (this.state === 'connecting') {
tries += 1 tries += 1
try { try {
const diff = lastConnect ? new Date().getTime()-lastConnect.getTime() : Infinity const diff = lastConnect ? new Date().getTime()-lastConnect.getTime() : Infinity
updates = await this.connectInternal ( result = await this.connectInternal (
options, options,
diff > this.connectOptions.connectCooldownMs ? 0 : this.connectOptions.connectCooldownMs diff > this.connectOptions.connectCooldownMs ? 0 : this.connectOptions.connectCooldownMs
) )
@@ -49,7 +49,7 @@ export class WAConnection extends Base {
if (!willReconnect) throw error if (!willReconnect) throw error
} }
} }
const result: WAOpenResult = { user: this.user, newConnection, ...(updates || {}) } result.newConnection = newConnection
this.emit ('open', result) this.emit ('open', result)
this.logger.info ('opened connection to WhatsApp Web') this.logger.info ('opened connection to WhatsApp Web')
@@ -100,14 +100,14 @@ export class WAConnection extends Base {
.removeAllListeners('error') .removeAllListeners('error')
.removeAllListeners('close') .removeAllListeners('close')
this.stopDebouncedTimeout() this.stopDebouncedTimeout()
resolve(authResult) resolve(authResult as WAOpenResult)
} catch (error) { } catch (error) {
reject(error) reject(error)
} }
}) })
this.conn.on('error', rejectAll) this.conn.on('error', rejectAll)
this.conn.on('close', () => rejectAll(new Error(DisconnectReason.close))) this.conn.on('close', () => rejectAll(new Error(DisconnectReason.close)))
}) as Promise<{ isNewUser: boolean }> }) as Promise<WAOpenResult>
) )
this.on ('ws-close', rejectAllOnWSClose) this.on ('ws-close', rejectAllOnWSClose)
@@ -120,7 +120,9 @@ export class WAConnection extends Base {
const result = await connect () const result = await connect ()
return result return result
} catch (error) { } catch (error) {
this.endConnection() if (this.conn) {
this.endConnection(error.message)
}
throw error throw error
} finally { } finally {
this.off ('ws-close', rejectAllOnWSClose) this.off ('ws-close', rejectAllOnWSClose)
@@ -142,8 +144,7 @@ export class WAConnection extends Base {
} catch (error) { } catch (error) {
this.logger.error ({ error }, `encountered error in decrypting message, closing: ${error}`) this.logger.error ({ error }, `encountered error in decrypting message, closing: ${error}`)
if (this.state === 'open') this.unexpectedDisconnect (DisconnectReason.badSession) this.unexpectedDisconnect(DisconnectReason.badSession)
else this.emit ('ws-close', new Error(DisconnectReason.badSession))
} }
if (this.shouldLogMessages) this.messageLog.push ({ tag: messageTag, json: JSON.stringify(json), fromMe: false }) if (this.shouldLogMessages) this.messageLog.push ({ tag: messageTag, json: JSON.stringify(json), fromMe: false })
@@ -171,18 +172,6 @@ export class WAConnection extends Base {
if (anyTriggered) return if (anyTriggered) return
if (this.state === 'open' && json[0] === 'Pong') {
if (!json[1]) {
this.unexpectedDisconnect(DisconnectReason.close)
this.logger.info('Connection terminated by phone, closing...')
return
}
if (this.phoneConnected !== json[1]) {
this.phoneConnected = json[1]
this.emit ('connection-phone-change', { connected: this.phoneConnected })
return
}
}
if (this.logger.level === 'debug') { if (this.logger.level === 'debug') {
this.logger.debug({ unhandled: true }, messageTag + ',' + JSON.stringify(json)) this.logger.debug({ unhandled: true }, messageTag + ',' + JSON.stringify(json))
} }
@@ -199,8 +188,8 @@ export class WAConnection extends Base {
check if it's been a suspicious amount of time since the server responded with our last seen check if it's been a suspicious amount of time since the server responded with our last seen
it could be that the network is down it could be that the network is down
*/ */
if (diff > KEEP_ALIVE_INTERVAL_MS+5000) this.unexpectedDisconnect (DisconnectReason.lost) if (diff > KEEP_ALIVE_INTERVAL_MS+5000) this.unexpectedDisconnect(DisconnectReason.lost)
else if (this.conn) this.send ('?,,') // if its all good, send a keep alive request else if (this.conn) this.send('?,,') // if its all good, send a keep alive request
}, KEEP_ALIVE_INTERVAL_MS) }, KEEP_ALIVE_INTERVAL_MS)
} }
} }

View File

@@ -11,9 +11,18 @@ export class WAConnection extends Base {
super () super ()
this.setMaxListeners (30) this.setMaxListeners (30)
// on disconnects // on disconnects
this.on ('CB:Cmd,type:disconnect', json => ( this.on('CB:Cmd,type:disconnect', json => (
this.state === 'open' && this.unexpectedDisconnect(json[1].kind || 'unknown') this.state === 'open' && this.unexpectedDisconnect(json[1].kind || 'unknown')
)) ))
this.on('CB:Pong', json => {
if (!json[1]) {
this.unexpectedDisconnect(DisconnectReason.close)
this.logger.info('Connection terminated by phone, closing...')
} else if (this.phoneConnected !== json[1]) {
this.phoneConnected = json[1]
this.emit ('connection-phone-change', { connected: this.phoneConnected })
}
})
// chats received // chats received
this.on('CB:response,type:chat', json => { this.on('CB:response,type:chat', json => {
if (json[1].duplicate || !json[2]) return if (json[1].duplicate || !json[2]) return
@@ -600,13 +609,11 @@ export class WAConnection extends Base {
/** when the connection is opening */ /** when the connection is opening */
on (event: 'connecting', listener: () => void): this on (event: 'connecting', listener: () => void): this
/** when the connection has been validated */ /** when the connection has been validated */
on (event: 'connection-validated', listener: (user: WAUser) => void): this on (event: 'connection-validated', listener: (item: { user: WAUser, auth: AuthenticationCredentials, isNewUser: boolean }) => void): this
/** when the connection has closed */ /** when the connection has closed */
on (event: 'close', listener: (err: {reason?: DisconnectReason | string, isReconnecting: boolean}) => void): this on (event: 'close', listener: (err: {reason?: DisconnectReason | string, isReconnecting: boolean}) => void): this
/** when the socket is closed */ /** when the socket is closed */
on (event: 'ws-close', listener: (err: {reason?: DisconnectReason | string}) => void): this on (event: 'ws-close', listener: (err: {reason?: DisconnectReason | string}) => void): this
/** when WA updates the credentials */
on (event: 'credentials-updated', listener: (auth: AuthenticationCredentials) => void): this
/** when a new QR is generated, ready for scanning */ /** when a new QR is generated, ready for scanning */
on (event: 'qr', listener: (qr: string) => void): this on (event: 'qr', listener: (qr: string) => void): this
/** when the connection to the phone changes */ /** when the connection to the phone changes */

View File

@@ -405,7 +405,7 @@ export interface WAOpenResult {
newConnection: boolean newConnection: boolean
user: WAUser user: WAUser
isNewUser: boolean isNewUser: boolean
hasNewChats?: boolean auth: AuthenticationCredentials
} }
export enum GroupSettingChange { export enum GroupSettingChange {
@@ -451,15 +451,14 @@ export type BaileysEvent =
'close' | 'close' |
'ws-close' | 'ws-close' |
'qr' | 'qr' |
'connection-validated' |
'connection-phone-change' | 'connection-phone-change' |
'contacts-received' | 'contacts-received' |
'chats-received' | 'chats-received' |
'initial-data-received' |
'chat-new' | 'chat-new' |
'chat-update' | 'chat-update' |
'group-participants-update' | 'group-participants-update' |
'group-update' | 'group-update' |
'received-pong' | 'received-pong' |
'credentials-updated' |
'blocklist-update' | 'blocklist-update' |
'contact-update' 'contact-update'