From d87e4e58976e22491f52a9aa133b203c7e6dfefd Mon Sep 17 00:00:00 2001 From: Adhiraj Date: Mon, 13 Jul 2020 16:32:52 +0530 Subject: [PATCH] Unified unexpected disconnect & takeover events --- Example/example.ts | 17 ++++++++--------- src/WAClient/Base.ts | 19 ------------------- src/WAConnection/Base.ts | 8 +++++++- src/WAConnection/Connect.ts | 23 ++++++++++++----------- src/WAConnection/Utils.ts | 4 +--- 5 files changed, 28 insertions(+), 43 deletions(-) diff --git a/Example/example.ts b/Example/example.ts index edcac84..47dda44 100644 --- a/Example/example.ts +++ b/Example/example.ts @@ -27,14 +27,6 @@ async function example() { fs.writeFileSync('./auth_info.json', JSON.stringify(authInfo, null, '\t')) // save this info to a file /* Note: one can take this auth_info.json file and login again from any computer without having to scan the QR code, and get full access to one's WhatsApp. Despite the convenience, be careful with this file */ - client.setOnDisconnect (async kind => { - if (kind === 'replaced') { - // uncomment to reconnect whenever the connection gets taken over from somewhere else - // await client.connect () - } else { - console.log ('oh no got logged out!') - } - }) client.setOnPresenceUpdate(json => console.log(json.id + ' presence is ' + json.type)) client.setOnMessageStatusChange(json => { const participant = json.participant ? ' (' + json.participant + ')' : '' // participant exists when the message is from a group @@ -121,7 +113,14 @@ async function example() { const batterylevel = parseInt(batteryLevelStr) console.log('battery level: ' + batterylevel) }) - client.setOnUnexpectedDisconnect(err => console.log('disconnected unexpectedly: ' + err)) + client.setOnUnexpectedDisconnect(reason => { + if (reason === 'replaced') { + // uncomment to reconnect whenever the connection gets taken over from somewhere else + // await client.connect () + } else { + console.log ('oh no got disconnected: ' + reason) + } + }) } example().catch((err) => console.log(`encountered error: ${err}`)) diff --git a/src/WAClient/Base.ts b/src/WAClient/Base.ts index 93aa79a..e93766f 100644 --- a/src/WAClient/Base.ts +++ b/src/WAClient/Base.ts @@ -5,29 +5,10 @@ import { WANode, WAMetric, WAFlag, - WAGroupCreateResponse, - WAGroupMetadata, - WAGroupModification, MessageLogLevel, } from '../WAConnection/Constants' -import { generateMessageTag } from '../WAConnection/Utils' export default class WhatsAppWebBase extends WAConnection { - /** Set the callback for when the connection is taken over somewhere else or logged out */ - setOnDisconnect(callback: (kind: 'replaced' | string | null) => void) { - this.registerCallback (['Cmd', 'type:disconnect'], json => { - this.log ('connection taken over elsewhere') - this.close () - callback (json[1].kind) - }) - } - /** Set the callback for unexpected disconnects */ - setOnUnexpectedDisconnect(callback: (error: Error) => void) { - this.unexpectedDisconnect = (err) => { - this.close() - callback(err) - } - } /** Set the callback for message status updates (when a message is delivered, read etc.) */ setOnMessageStatusChange(callback: (update: MessageStatusUpdate) => void) { const func = (json) => { diff --git a/src/WAConnection/Base.ts b/src/WAConnection/Base.ts index b8e9385..a3b83c9 100644 --- a/src/WAConnection/Base.ts +++ b/src/WAConnection/Base.ts @@ -51,7 +51,13 @@ export default class WAConnectionBase { protected decoder = new Decoder() /** What to do when you need the phone to authenticate the connection (generate QR code by default) */ onReadyForPhoneAuthentication = generateQRCode - unexpectedDisconnect = (err) => this.close() + unexpectedDisconnect = (err: string) => this.close() + + /** Set the callback for unexpected disconnects including take over events, log out events etc. */ + setOnUnexpectedDisconnect(callback: (error: string) => void) { + this.registerCallback (['Cmd', 'type:disconnect'], json => this.unexpectedDisconnect(json[1].kind)) + this.unexpectedDisconnect = err => { this.close(); callback(err) } + } /** * base 64 encode the authentication credentials and return them * these can then be used to login again by passing the object to the connect () function. diff --git a/src/WAConnection/Connect.ts b/src/WAConnection/Connect.ts index eb476ec..b1bd874 100644 --- a/src/WAConnection/Connect.ts +++ b/src/WAConnection/Connect.ts @@ -39,18 +39,19 @@ export default class WAConnectionConnector extends WAConnectionValidator { this.log('connected to WhatsApp Web, authenticating...') // start sending keep alive requests (keeps the WebSocket alive & updates our last seen) this.authenticate() - .then((user) => { - this.startKeepAliveRequest() - resolve(user) - }) - .catch(reject) - }) - this.conn.on('message', (m) => this.onMessageRecieved(m)) // in WhatsAppWeb.Recv.js - this.conn.on('error', (error) => { - // if there was an error in the WebSocket - this.close() - reject(error) + .then(user => { + this.startKeepAliveRequest() + + this.conn.on ('error', null) + this.conn.on ('close', () => this.unexpectedDisconnect ('closed')) + + resolve(user) + }) + .catch(reject) }) + this.conn.on('message', m => this.onMessageRecieved(m)) + // if there was an error in the WebSocket + this.conn.on('error', error => { this.close(); reject(error) }) }) promise = Utils.promiseTimeout(timeoutMs, promise) return promise.catch(err => { diff --git a/src/WAConnection/Utils.ts b/src/WAConnection/Utils.ts index fc55902..bff4163 100644 --- a/src/WAConnection/Utils.ts +++ b/src/WAConnection/Utils.ts @@ -53,9 +53,7 @@ export function randomBytes(length) { } export const createTimeout = (timeout) => new Promise(resolve => setTimeout(resolve, timeout)) export function promiseTimeout(ms: number, promise: Promise) { - if (!ms) { - return promise - } + if (!ms) return promise // Create a promise that rejects in milliseconds const timeout = new Promise((_, reject) => { const id = setTimeout(() => {