diff --git a/src/Socket/chats.ts b/src/Socket/chats.ts index ee34528..de74261 100644 --- a/src/Socket/chats.ts +++ b/src/Socket/chats.ts @@ -339,7 +339,7 @@ export const makeChatsSocket = (config: SocketConfig) => { name, version: state.version.toString(), // return snapshot if being synced from scratch - return_snapshot: (!state.version).toString() + 'return_snapshot': (!state.version).toString() } }) } diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index 7b948ec..ce1fc11 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -1,4 +1,5 @@ +import NodeCache from 'node-cache' import { proto } from '../../WAProto' import { KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT } from '../Defaults' import { MessageReceiptType, MessageRelayOptions, MessageUserReceipt, SocketConfig, WACallEvent, WAMessageKey, WAMessageStubType, WAPatchName } from '../Types' @@ -36,8 +37,14 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { /** this mutex ensures that each retryRequest will wait for the previous one to finish */ const retryMutex = makeMutex() - const msgRetryMap = config.msgRetryCounterMap || { } - const callOfferData: { [id: string]: WACallEvent } = { } + const msgRetryCache = config.msgRetryCounterCache || new NodeCache({ + stdTTL: 60 * 60, // 1 hour + useClones: false + }) + const callOfferCache = config.callOfferCache || new NodeCache({ + stdTTL: 5 * 60, // 5 mins + useClones: false + }) let sendActiveReceipts = false @@ -90,15 +97,15 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const sendRetryRequest = async(node: BinaryNode, forceIncludeKeys = false) => { const msgId = node.attrs.id - let retryCount = msgRetryMap[msgId] || 0 + let retryCount = msgRetryCache.get(msgId) || 0 if(retryCount >= 5) { logger.debug({ retryCount, msgId }, 'reached retry limit, clearing') - delete msgRetryMap[msgId] + msgRetryCache.del(msgId) return } retryCount += 1 - msgRetryMap[msgId] = retryCount + msgRetryCache.set(msgId, retryCount) const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds @@ -362,13 +369,14 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const willSendMessageAgain = (id: string, participant: string) => { const key = `${id}:${participant}` - const retryCount = msgRetryMap[key] || 0 + const retryCount = msgRetryCache.get(key) || 0 return retryCount < 5 } const updateSendMessageAgainCount = (id: string, participant: string) => { const key = `${id}:${participant}` - msgRetryMap[key] = (msgRetryMap[key] || 0) + 1 + const newValue = (msgRetryCache.get(key) || 0) + 1 + msgRetryCache.set(key, newValue) } const sendMessagesAgain = async( @@ -618,18 +626,20 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { if(status === 'offer') { call.isVideo = !!getBinaryNodeChild(infoChild, 'video') call.isGroup = infoChild.attrs.type === 'group' - callOfferData[call.id] = call + callOfferCache.set(call.id, call) } + const existingCall = callOfferCache.get(call.id) + // use existing call info to populate this event - if(callOfferData[call.id]) { - call.isVideo = callOfferData[call.id].isVideo - call.isGroup = callOfferData[call.id].isGroup + if(existingCall) { + call.isVideo = existingCall.isVideo + call.isGroup = existingCall.isGroup } // delete data once call has ended if(status === 'reject' || status === 'accept' || status === 'timeout') { - delete callOfferData[call.id] + callOfferCache.del(call.id) } ev.emit('call', [call]) diff --git a/src/Types/Socket.ts b/src/Types/Socket.ts index 5144fdd..b43d539 100644 --- a/src/Types/Socket.ts +++ b/src/Types/Socket.ts @@ -11,8 +11,6 @@ import { MediaConnInfo } from './Message' export type WAVersion = [number, number, number] export type WABrowserDescription = [string, string, string] -export type MessageRetryMap = { [msgId: string]: number } - export type SocketConfig = { /** the WS url to connect to WA */ waWebSocketUrl: string | URL @@ -43,21 +41,23 @@ export type SocketConfig = { /** time to wait between sending new retry requests */ retryRequestDelayMs: number /** time to wait for the generation of the next QR in ms */ - qrTimeout?: number; + qrTimeout?: number /** provide an auth state object to maintain the auth state */ auth: AuthenticationState /** manage history processing with this control; by default will sync up everything */ shouldSyncHistoryMessage: (msg: proto.Message.IHistorySyncNotification) => boolean /** transaction capability options for SignalKeyStore */ transactionOpts: TransactionCapabilityOptions - /** provide a cache to store a user's device list */ - userDevicesCache?: NodeCache /** marks the client as online whenever the socket successfully connects */ markOnlineOnConnect: boolean /** * map to store the retry counts for failed messages; * used to determine whether to retry a message or not */ - msgRetryCounterMap?: MessageRetryMap + msgRetryCounterCache?: NodeCache + /** provide a cache to store a user's device list */ + userDevicesCache?: NodeCache + /** cache to store call offers */ + callOfferCache?: NodeCache /** width for link preview images */ linkPreviewImageThumbnailWidth: number /** Should Baileys ask the phone for full history, will be received async */ @@ -92,7 +92,7 @@ export type SocketConfig = { } /** options for axios */ - options: AxiosRequestConfig + options: AxiosRequestConfig<{}> /** * fetch a message from your store * implement this so that messages failed to send (solves the "this message can take a while" issue) can be retried