chore: more unification of legacy APIs

1. unify waitForConnectionUpdate
2. unify printing QR in terminal
This commit is contained in:
Adhiraj Singh
2021-12-18 22:18:51 +05:30
parent 02dd8c93a6
commit f61f553e01
5 changed files with 54 additions and 80 deletions

View File

@@ -42,7 +42,6 @@ export const DEFAULT_LEGACY_CONNECTION_CONFIG: LegacySocketConfig = {
waWebSocketUrl: 'wss://web.whatsapp.com/ws',
phoneResponseTimeMs: 20_000,
expectResponseTimeout: 60_000,
pendingRequestTimeoutMs: 60_000
}
export const MEDIA_PATH_MAP: { [T in MediaType]: string } = {

View File

@@ -1,7 +1,7 @@
import { Boom } from '@hapi/boom'
import EventEmitter from "events"
import { LegacyBaileysEventEmitter, BaileysEventMap, LegacySocketConfig, CurveKeyPair, WAInitResponse, ConnectionState, DisconnectReason, LegacyAuthenticationCreds } from "../Types"
import { newLegacyAuthCreds, promiseTimeout, computeChallengeResponse, validateNewConnection, Curve } from "../Utils"
import { LegacyBaileysEventEmitter, LegacySocketConfig, CurveKeyPair, WAInitResponse, ConnectionState, DisconnectReason } from "../Types"
import { newLegacyAuthCreds, bindWaitForConnectionUpdate, computeChallengeResponse, validateNewConnection, Curve, printQRIfNecessaryListener } from "../Utils"
import { makeSocket } from "./socket"
const makeAuthSocket = (config: LegacySocketConfig) => {
@@ -10,7 +10,6 @@ const makeAuthSocket = (config: LegacySocketConfig) => {
version,
browser,
connectTimeoutMs,
pendingRequestTimeoutMs,
printQRInTerminal,
auth: initialAuthInfo
} = config
@@ -74,34 +73,6 @@ const makeAuthSocket = (config: LegacySocketConfig) => {
new Boom('Logged Out', { statusCode: DisconnectReason.loggedOut })
)
}
/** Waits for the connection to WA to open up */
const waitForConnection = async(waitInfinitely: boolean = false) => {
if(state.connection === 'open') return
let listener: (item: BaileysEventMap<LegacyAuthenticationCreds>['connection.update']) => void
const timeout = waitInfinitely ? undefined : pendingRequestTimeoutMs
if(timeout < 0) {
throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed })
}
await (
promiseTimeout(
timeout,
(resolve, reject) => {
listener = ({ connection, lastDisconnect }) => {
if(connection === 'open') resolve()
else if(connection == 'close') {
reject(lastDisconnect.error || new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }))
}
}
ev.on('connection.update', listener)
}
)
.finally(() => (
ev.off('connection.update', listener)
))
)
}
const updateEncKeys = () => {
// update the keys so we can decrypt traffic
@@ -246,14 +217,7 @@ const makeAuthSocket = (config: LegacySocketConfig) => {
})
if(printQRInTerminal) {
ev.on('connection.update', async({ qr }) => {
if(qr) {
const QR = await import('qrcode-terminal').catch(err => {
logger.error('QR code terminal not added as dependency')
})
QR?.generate(qr, { small: true })
}
})
printQRIfNecessaryListener(ev, logger)
}
return {
@@ -261,9 +225,10 @@ const makeAuthSocket = (config: LegacySocketConfig) => {
state,
authInfo,
ev,
waitForConnection,
canLogin,
logout
logout,
/** Waits for the connection to WA to reach a state */
waitForConnectionUpdate: bindWaitForConnectionUpdate(ev)
}
}
export default makeAuthSocket

View File

@@ -4,8 +4,8 @@ import { promisify } from "util"
import WebSocket from "ws"
import { randomBytes } from 'crypto'
import { proto } from '../../WAProto'
import { DisconnectReason, SocketConfig, BaileysEventEmitter, ConnectionState, AuthenticationCreds } from "../Types"
import { Curve, generateRegistrationNode, configureSuccessfulPairing, generateLoginNode, encodeBigEndian, promiseTimeout, generateOrGetPreKeys, xmppSignedPreKey, xmppPreKey, getPreKeys, makeNoiseHandler, useSingleFileAuthState, addTransactionCapability } from "../Utils"
import { DisconnectReason, SocketConfig, BaileysEventEmitter, AuthenticationCreds } from "../Types"
import { Curve, generateRegistrationNode, configureSuccessfulPairing, generateLoginNode, encodeBigEndian, promiseTimeout, generateOrGetPreKeys, xmppSignedPreKey, xmppPreKey, getPreKeys, makeNoiseHandler, useSingleFileAuthState, addTransactionCapability, bindWaitForConnectionUpdate, printQRIfNecessaryListener } from "../Utils"
import { DEFAULT_ORIGIN, DEF_TAG_PREFIX, DEF_CALLBACK_PREFIX, KEY_BUNDLE_TYPE } from "../Defaults"
import { assertNodeErrorFree, BinaryNode, encodeBinaryNode, S_WHATSAPP_NET, getBinaryNodeChild } from '../WABinary'
@@ -389,28 +389,6 @@ export const makeSocket = ({
end(new Boom('Intentional Logout', { statusCode: DisconnectReason.loggedOut }))
}
/** Waits for the connection to WA to reach a state */
const waitForConnectionUpdate = async(check: (u: Partial<ConnectionState>) => boolean, timeoutMs?: number) => {
let listener: (item: Partial<ConnectionState>) => void
await (
promiseTimeout(
timeoutMs,
(resolve, reject) => {
listener = (update) => {
if(check(update)) {
resolve()
} else if(update.connection == 'close') {
reject(update.lastDisconnect?.error || new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }))
}
}
ev.on('connection.update', listener)
}
)
.finally(() => (
ev.off('connection.update', listener)
))
)
}
ws.on('message', onMessageRecieved)
ws.on('open', validateConnection)
@@ -422,15 +400,6 @@ export const makeSocket = ({
})
// QR gen
ws.on('CB:iq,type:set,pair-device', async (stanza: BinaryNode) => {
const postQR = async(qr: string) => {
if(printQRInTerminal) {
const QR = await import('qrcode-terminal').catch(err => {
logger.error('add `qrcode-terminal` as a dependency to auto-print QR')
})
QR?.generate(qr, { small: true })
}
}
const iq: BinaryNode = {
tag: 'iq',
attrs: {
@@ -457,7 +426,6 @@ export const makeSocket = ({
const qr = [ref, noiseKeyB64, identityKeyB64, advB64].join(',')
ev.emit('connection.update', { qr })
postQR(qr)
qrTimer = setTimeout(genPairQR, qrMs)
qrMs = 20_000 // shorter subsequent qrs
@@ -539,6 +507,10 @@ export const makeSocket = ({
// update credentials when required
ev.on('creds.update', update => Object.assign(creds, update))
if(printQRInTerminal) {
printQRIfNecessaryListener(ev, logger)
}
return {
type: 'md' as 'md',
ws,
@@ -560,7 +532,8 @@ export const makeSocket = ({
sendNode,
logout,
end,
waitForConnectionUpdate
/** Waits for the connection to WA to reach a state */
waitForConnectionUpdate: bindWaitForConnectionUpdate(ev)
}
}
export type Socket = ReturnType<typeof makeSocket>

View File

@@ -76,8 +76,6 @@ export type LegacySocketConfig = CommonSocketConfig<LegacyAuthenticationCreds> &
phoneResponseTimeMs: number
/** max time for WA server to respond before error with 422 */
expectResponseTimeout: number
pendingRequestTimeoutMs: number
}
export type LegacyBaileysEventEmitter = CommonBaileysEventEmitter<LegacyAuthenticationCreds>

View File

@@ -1,7 +1,10 @@
import { Boom } from '@hapi/boom'
import { randomBytes } from 'crypto'
import { platform, release } from 'os'
import { Logger } from 'pino'
import { ConnectionState } from '..'
import { proto } from '../../WAProto'
import { CommonBaileysEventEmitter, DisconnectReason } from '../Types'
import { Binary } from '../WABinary'
const PLATFORM_MAP = {
@@ -176,4 +179,40 @@ export async function promiseTimeout<T>(ms: number, promise: (resolve: (v?: T)=>
return p as Promise<T>
}
// generate a random ID to attach to a message
export const generateMessageID = () => 'BAE5' + randomBytes(6).toString('hex').toUpperCase()
export const generateMessageID = () => 'BAE5' + randomBytes(6).toString('hex').toUpperCase()
export const bindWaitForConnectionUpdate = (ev: CommonBaileysEventEmitter<any>) => (
async(check: (u: Partial<ConnectionState>) => boolean, timeoutMs?: number) => {
let listener: (item: Partial<ConnectionState>) => void
await (
promiseTimeout(
timeoutMs,
(resolve, reject) => {
listener = (update) => {
if(check(update)) {
resolve()
} else if(update.connection == 'close') {
reject(update.lastDisconnect?.error || new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }))
}
}
ev.on('connection.update', listener)
}
)
.finally(() => (
ev.off('connection.update', listener)
))
)
}
)
export const printQRIfNecessaryListener = (ev: CommonBaileysEventEmitter<any>, logger: Logger) => {
ev.on('connection.update', async({ qr }) => {
if(qr) {
const QR = await import('qrcode-terminal')
.catch(err => {
logger.error('QR code terminal not added as dependency')
})
QR?.generate(qr, { small: true })
}
})
}