mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Handle updating of credentials
This commit is contained in:
@@ -22,6 +22,13 @@ async function example() {
|
|||||||
// attempt to reconnect at most 10 times
|
// attempt to reconnect at most 10 times
|
||||||
conn.connectOptions.maxRetries = 10
|
conn.connectOptions.maxRetries = 10
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
|
||||||
// loads the auth file credentials if present
|
// loads the auth file credentials if present
|
||||||
fs.existsSync('./auth_info.json') && conn.loadAuthInfo ('./auth_info.json')
|
fs.existsSync('./auth_info.json') && conn.loadAuthInfo ('./auth_info.json')
|
||||||
// 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
|
||||||
@@ -34,9 +41,6 @@ async function example() {
|
|||||||
console.log('you have ' + conn.chats.length + ' chats & ' + Object.keys(conn.contacts).length + ' contacts')
|
console.log('you have ' + conn.chats.length + ' chats & ' + Object.keys(conn.contacts).length + ' contacts')
|
||||||
console.log ('you have ' + unread.length + ' unread messages')
|
console.log ('you have ' + unread.length + ' unread messages')
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
/* Note: one can take this auth_info.json file and login again from any computer without having to scan the QR code,
|
/* 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 */
|
and get full access to one's WhatsApp. Despite the convenience, be careful with this file */
|
||||||
conn.on ('user-presence-update', json => console.log(json.id + ' presence is ' + json.type))
|
conn.on ('user-presence-update', json => console.log(json.id + ' presence is ' + json.type))
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -84,14 +84,19 @@ console.log ("oh hello " + conn.user.name + "! You connected via a proxy")
|
|||||||
|
|
||||||
You obviously don't want to keep scanning the QR code every time you want to connect.
|
You obviously don't want to keep scanning the QR code every time you want to connect.
|
||||||
|
|
||||||
So, do the following every time you open a new connection:
|
So, you can save the credentials to log back in via:
|
||||||
``` ts
|
``` ts
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
|
||||||
const conn = new WAConnection()
|
const conn = new WAConnection()
|
||||||
await conn.connect() // connect first
|
// this will be called as soon as the credentials are updated
|
||||||
const creds = conn.base64EncodedAuthInfo () // contains all the keys you need to restore a session
|
conn.on ('credentials-updated', () => {
|
||||||
fs.writeFileSync('./auth_info.json', JSON.stringify(creds, null, '\t')) // save JSON to file
|
// 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
|
||||||
|
})
|
||||||
|
await conn.connect() // connect
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, to restore a session:
|
Then, to restore a session:
|
||||||
@@ -108,11 +113,13 @@ await conn.connect()
|
|||||||
|
|
||||||
If you're considering switching from a Chromium/Puppeteer based library, you can use WhatsApp Web's Browser credentials to restore sessions too:
|
If you're considering switching from a Chromium/Puppeteer based library, you can use WhatsApp Web's Browser credentials to restore sessions too:
|
||||||
``` ts
|
``` ts
|
||||||
conn.loadAuthInfo ('./auth_info_browser.json') // use loaded credentials & timeout in 20s
|
conn.loadAuthInfo ('./auth_info_browser.json')
|
||||||
await conn.connect() // works the same
|
await conn.connect() // works the same
|
||||||
```
|
```
|
||||||
See the browser credentials type in the docs.
|
See the browser credentials type in the docs.
|
||||||
|
|
||||||
|
**Note**: Upon every successive connection, WA can update part of the stored credentials. Whenever that happens, the `credentials-updated` event is triggered, and you should probably update your saved credentials upon receiving that event. Not doing so *may* lead WA to log you out after a few weeks with a 419 error code.
|
||||||
|
|
||||||
## QR Callback
|
## QR Callback
|
||||||
|
|
||||||
If you want to do some custom processing with the QR code used to authenticate, you can register for the following event:
|
If you want to do some custom processing with the QR code used to authenticate, you can register for the following event:
|
||||||
@@ -143,6 +150,10 @@ on (event: 'open', listener: (result: WAOpenResult) => void): this
|
|||||||
on (event: 'connecting', listener: () => void): this
|
on (event: 'connecting', listener: () => 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 connection has closed */
|
||||||
|
on (event: 'intermediate-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 */
|
||||||
|
|||||||
@@ -33,10 +33,15 @@ describe('Test Connect', () => {
|
|||||||
console.log('please be ready to scan with your phone')
|
console.log('please be ready to scan with your phone')
|
||||||
|
|
||||||
const conn = new WAConnection()
|
const conn = new WAConnection()
|
||||||
|
|
||||||
|
let credentialsUpdateCalled = false
|
||||||
|
conn.on ('credentials-updated', () => credentialsUpdateCalled = true)
|
||||||
|
|
||||||
await conn.connect ()
|
await conn.connect ()
|
||||||
assert.ok(conn.user?.jid)
|
assert.ok(conn.user?.jid)
|
||||||
assert.ok(conn.user?.phone)
|
assert.ok(conn.user?.phone)
|
||||||
assert.ok (conn.user?.imgUrl || conn.user.imgUrl === '')
|
assert.ok (conn.user?.imgUrl || conn.user.imgUrl === '')
|
||||||
|
assert.ok (credentialsUpdateCalled)
|
||||||
|
|
||||||
assertChatDBIntegrity (conn)
|
assertChatDBIntegrity (conn)
|
||||||
|
|
||||||
@@ -45,15 +50,19 @@ describe('Test Connect', () => {
|
|||||||
})
|
})
|
||||||
it('should reconnect', async () => {
|
it('should reconnect', async () => {
|
||||||
const conn = new WAConnection()
|
const conn = new WAConnection()
|
||||||
|
|
||||||
|
let credentialsUpdateCalled = false
|
||||||
|
conn.on ('credentials-updated', () => credentialsUpdateCalled = true)
|
||||||
|
|
||||||
await conn.loadAuthInfo (auth).connect ()
|
await conn.loadAuthInfo (auth).connect ()
|
||||||
assert.ok(conn.user)
|
assert.ok(conn.user)
|
||||||
assert.ok(conn.user.jid)
|
assert.ok(conn.user.jid)
|
||||||
|
assert.ok (credentialsUpdateCalled)
|
||||||
|
|
||||||
assertChatDBIntegrity (conn)
|
assertChatDBIntegrity (conn)
|
||||||
await conn.logout()
|
await conn.logout()
|
||||||
conn.loadAuthInfo(auth)
|
conn.loadAuthInfo(auth)
|
||||||
|
|
||||||
await conn.connect()
|
await conn.connect()
|
||||||
.then (() => assert.fail('should not have reconnected'))
|
.then (() => assert.fail('should not have reconnected'))
|
||||||
.catch (err => {
|
.catch (err => {
|
||||||
|
|||||||
@@ -112,10 +112,22 @@ export class WAConnection extends Base {
|
|||||||
}) as WAUser
|
}) as WAUser
|
||||||
|
|
||||||
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) {
|
||||||
|
console.log (`change: ${this.authInfo.clientToken}, ${json.clientToken}`)
|
||||||
|
this.authInfo = { ...this.authInfo, clientToken: json.clientToken }
|
||||||
|
credsChanged = true
|
||||||
|
}
|
||||||
|
if (json.serverToken && json.serverToken !== this.authInfo.serverToken) {
|
||||||
|
this.authInfo = { ...this.authInfo, serverToken: json.serverToken }
|
||||||
|
credsChanged = true
|
||||||
|
}
|
||||||
|
if (credsChanged) {
|
||||||
|
this.emit ('credentials-updated', this.authInfo)
|
||||||
|
}
|
||||||
return onValidationSuccess()
|
return onValidationSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
const secret = Buffer.from(json.secret, 'base64')
|
const secret = Buffer.from(json.secret, 'base64')
|
||||||
if (secret.length !== 144) {
|
if (secret.length !== 144) {
|
||||||
throw new Error ('incorrect secret length received: ' + secret.length)
|
throw new Error ('incorrect secret length received: ' + secret.length)
|
||||||
@@ -153,6 +165,8 @@ 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()
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as QR from 'qrcode-terminal'
|
import * as QR from 'qrcode-terminal'
|
||||||
import { WAConnection as Base } from './3.Connect'
|
import { WAConnection as Base } from './3.Connect'
|
||||||
import { WAMessageStatusUpdate, WAMessage, WAContact, WAChat, WAMessageProto, WA_MESSAGE_STUB_TYPE, WA_MESSAGE_STATUS_TYPE, MessageLogLevel, PresenceUpdate, BaileysEvent, DisconnectReason, WANode, WAOpenResult, Presence } from './Constants'
|
import { WAMessageStatusUpdate, WAMessage, WAContact, WAChat, WAMessageProto, WA_MESSAGE_STUB_TYPE, WA_MESSAGE_STATUS_TYPE, MessageLogLevel, PresenceUpdate, BaileysEvent, DisconnectReason, WANode, WAOpenResult, Presence, AuthenticationCredentials } from './Constants'
|
||||||
import { whatsappID, unixTimestampSeconds, isGroupID, toNumber, GET_MESSAGE_ID, WA_MESSAGE_ID, WA_MESSAGE_KEY } from './Utils'
|
import { whatsappID, unixTimestampSeconds, isGroupID, toNumber, GET_MESSAGE_ID, WA_MESSAGE_ID, WA_MESSAGE_KEY } from './Utils'
|
||||||
import KeyedDB from '@adiwajshing/keyed-db'
|
import KeyedDB from '@adiwajshing/keyed-db'
|
||||||
import { Mutex } from './Mutex'
|
import { Mutex } from './Mutex'
|
||||||
@@ -322,6 +322,8 @@ export class WAConnection extends Base {
|
|||||||
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 connection has closed */
|
/** when the connection has closed */
|
||||||
on (event: 'intermediate-close', listener: (err: {reason?: DisconnectReason | string}) => void): this
|
on (event: 'intermediate-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 */
|
||||||
|
|||||||
@@ -431,4 +431,5 @@ export type BaileysEvent =
|
|||||||
'group-participants-demote' |
|
'group-participants-demote' |
|
||||||
'group-settings-update' |
|
'group-settings-update' |
|
||||||
'group-description-update' |
|
'group-description-update' |
|
||||||
'received-pong'
|
'received-pong' |
|
||||||
|
'credentials-updated'
|
||||||
Reference in New Issue
Block a user