From 211a899ed4f56d85fc1acbb9439de8865ac4d777 Mon Sep 17 00:00:00 2001 From: Adhiraj Singh Date: Mon, 25 Apr 2022 09:11:03 +0530 Subject: [PATCH] feat: handle stream:errors more gracefully --- src/Socket/socket.ts | 15 ++++++++++----- src/Utils/generics.ts | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index 6fe8f55..65f3e49 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -5,8 +5,8 @@ import WebSocket from 'ws' import { proto } from '../../WAProto' import { DEF_CALLBACK_PREFIX, DEF_TAG_PREFIX, DEFAULT_ORIGIN, INITIAL_PREKEY_COUNT, MIN_PREKEY_COUNT } from '../Defaults' import { AuthenticationCreds, BaileysEventEmitter, BaileysEventMap, DisconnectReason, SocketConfig } from '../Types' -import { addTransactionCapability, bindWaitForConnectionUpdate, configureSuccessfulPairing, Curve, generateLoginNode, generateMdTagPrefix, generateRegistrationNode, getNextPreKeysNode, makeNoiseHandler, printQRIfNecessaryListener, promiseTimeout, useSingleFileAuthState } from '../Utils' -import { assertNodeErrorFree, BinaryNode, encodeBinaryNode, getBinaryNodeChild, getBinaryNodeChildren, S_WHATSAPP_NET } from '../WABinary' +import { addTransactionCapability, bindWaitForConnectionUpdate, configureSuccessfulPairing, Curve, generateLoginNode, generateMdTagPrefix, generateRegistrationNode, getErrorCodeFromStreamErrorReason, getNextPreKeysNode, makeNoiseHandler, printQRIfNecessaryListener, promiseTimeout, useSingleFileAuthState } from '../Utils' +import { assertNodeErrorFree, BinaryNode, encodeBinaryNode, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildren, S_WHATSAPP_NET } from '../WABinary' /** * Connects to WA servers and performs: @@ -528,10 +528,15 @@ export const makeSocket = ({ }) ws.on('CB:stream:error', (node: BinaryNode) => { - logger.error({ error: node }, 'stream errored out') + logger.error({ node }, 'stream errored out') - const statusCode = +(node.attrs.code || DisconnectReason.restartRequired) - end(new Boom('Stream Errored', { statusCode, data: node })) + const [reasonNode] = getAllBinaryNodeChildren(node) + const reason = reasonNode?.tag || 'unknown' + const statusCode = +( + node.attrs.code + || getErrorCodeFromStreamErrorReason(reason) + ) + end(new Boom(`Stream Errored (${reason})`, { statusCode, data: node })) }) // stream fail, possible logout ws.on('CB:failure', (node: BinaryNode) => { diff --git a/src/Utils/generics.ts b/src/Utils/generics.ts index 82622c7..07ed63c 100644 --- a/src/Utils/generics.ts +++ b/src/Utils/generics.ts @@ -252,7 +252,10 @@ const STATUS_MAP: { [_: string]: proto.WebMessageInfo.WebMessageInfoStatus } = { 'read': proto.WebMessageInfo.WebMessageInfoStatus.READ, 'read-self': proto.WebMessageInfo.WebMessageInfoStatus.READ } - +/** + * Given a type of receipt, returns what the new status of the message should be + * @param type type from receipt + */ export const getStatusFromReceiptType = (type: string | undefined) => { const status = STATUS_MAP[type] if(typeof type === 'undefined') { @@ -261,3 +264,15 @@ export const getStatusFromReceiptType = (type: string | undefined) => { return status } + +const CODE_MAP: { [_: string]: DisconnectReason } = { + conflict: DisconnectReason.connectionReplaced +} + +/** + * Stream errors generally provide a reason, map that to a baileys DisconnectReason + * @param reason the string reason given, eg. "conflict" + */ +export const getErrorCodeFromStreamErrorReason = (reason: string) => { + return CODE_MAP[reason] || DisconnectReason.badSession +} \ No newline at end of file