From 59f834ca39e6272ff75091cb905edfbba7a375b9 Mon Sep 17 00:00:00 2001 From: Adhiraj Singh Date: Sun, 3 Apr 2022 11:27:13 +0530 Subject: [PATCH] fix: handle receipts more accurately 1. only send timestamp with read receipts 2. use unix timestamp in seconds instead of millis 3. use "sender" receipts for own messages --- src/Socket/messages-recv.ts | 22 +++++++++++++++------- src/Socket/messages-send.ts | 27 ++++++++++++++++----------- src/Types/Message.ts | 2 +- src/Utils/decode-wa-message.ts | 5 +++-- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index 42fcbff..90ba536 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -1,11 +1,11 @@ import { proto } from '../../WAProto' import { KEY_BUNDLE_TYPE } from '../Defaults' -import { BaileysEventMap, MessageUserReceipt, SocketConfig, WAMessageStubType } from '../Types' +import { BaileysEventMap, MessageReceiptType, MessageUserReceipt, SocketConfig, WAMessageStubType } from '../Types' import { debouncedTimeout, decodeMessageStanza, delay, encodeBigEndian, generateSignalPubKey, getStatusFromReceiptType, normalizeMessageContent, xmppPreKey, xmppSignedPreKey } from '../Utils' import { makeKeyedMutex, makeMutex } from '../Utils/make-mutex' import processMessage from '../Utils/process-message' -import { areJidsSameUser, BinaryNode, BinaryNodeAttributes, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary' +import { areJidsSameUser, BinaryNode, BinaryNodeAttributes, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, isJidUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary' import { makeChatsSocket } from './chats' import { extractGroupMetadata } from './groups' @@ -441,7 +441,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { // recv a message ws.on('CB:message', (stanza: BinaryNode) => { - const { fullMessage: msg, category, decryptionTask } = decodeMessageStanza(stanza, authState) + const { fullMessage: msg, category, author, decryptionTask } = decodeMessageStanza(stanza, authState) processingMutex.mutex( msg.key.remoteJid!, async() => { @@ -467,11 +467,19 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } else { await sendMessageAck(stanza, { class: 'receipt' }) // no type in the receipt => message delivered - await sendReceipt(msg.key.remoteJid!, msg.key.participant, [msg.key.id!], undefined) - - if(category === 'peer') { - await sendReceipt(msg.key.remoteJid!, undefined, [msg.key.id], 'peer_msg') + let type: MessageReceiptType = undefined + let participant = msg.key.participant + if(category === 'peer') { // special peer message + type = 'peer_msg' + } else if(msg.key.fromMe) { // message was sent by us from a different device + type = 'sender' + // need to specially handle this case + if(isJidUser(msg.key.remoteJid)) { + participant = author + } } + + await sendReceipt(msg.key.remoteJid!, participant, [msg.key.id!], type) } msg.key.remoteJid = jidNormalizedUser(msg.key.remoteJid!) diff --git a/src/Socket/messages-send.ts b/src/Socket/messages-send.ts index 964eb3b..77dd074 100644 --- a/src/Socket/messages-send.ts +++ b/src/Socket/messages-send.ts @@ -3,8 +3,8 @@ import NodeCache from 'node-cache' import { proto } from '../../WAProto' import { WA_DEFAULT_EPHEMERAL } from '../Defaults' import { AnyMessageContent, MediaConnInfo, MessageReceiptType, MessageRelayOptions, MiscMessageGenerationOptions, SocketConfig } from '../Types' -import { encodeWAMessage, encryptSenderKeyMsgSignalProto, encryptSignalProto, extractDeviceJids, generateMessageID, generateWAMessage, getWAUploadToServer, jidToSignalProtocolAddress, parseAndInjectE2ESessions } from '../Utils' -import { BinaryNode, BinaryNodeAttributes, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, jidDecode, jidEncode, jidNormalizedUser, JidWithDevice, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary' +import { encodeWAMessage, encryptSenderKeyMsgSignalProto, encryptSignalProto, extractDeviceJids, generateMessageID, generateWAMessage, getWAUploadToServer, jidToSignalProtocolAddress, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils' +import { BinaryNode, BinaryNodeAttributes, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, isJidUser, jidDecode, jidEncode, jidNormalizedUser, JidWithDevice, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary' import { makeGroupsSocket } from './groups' export const makeMessagesSocket = (config: SocketConfig) => { @@ -85,22 +85,27 @@ export const makeMessagesSocket = (config: SocketConfig) => { tag: 'receipt', attrs: { id: messageIds[0], - to: jid, }, } - const isProtoReceipt = type === 'hist_sync' || type === 'peer_msg' - if(!isProtoReceipt) { - node.attrs.t = Date.now().toString() + const isReadReceipt = type === 'read' || type === 'read-self' + if(isReadReceipt) { + node.attrs.t = unixTimestampSeconds().toString() + } + + if(type === 'sender' && isJidUser(jid)) { + node.attrs.recipient = jid + node.attrs.to = participant + } else { + node.attrs.to = jid + if(participant) { + node.attrs.participant = participant + } } if(type) { node.attrs.type = type } - if(participant) { - node.attrs.participant = participant - } - const remainingMessageIds = messageIds.slice(1) if(remainingMessageIds.length) { node.content = [ @@ -115,7 +120,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { ] } - logger.debug({ jid, messageIds, type }, 'sending receipt for messages') + logger.debug({ attrs: node.attrs, messageIds }, 'sending receipt for messages') await sendNode(node) } diff --git a/src/Types/Message.ts b/src/Types/Message.ts index 0675572..acbc41a 100644 --- a/src/Types/Message.ts +++ b/src/Types/Message.ts @@ -24,7 +24,7 @@ export type MessageType = keyof proto.Message export type DownloadableMessage = { mediaKey?: Uint8Array, directPath?: string, url?: string } -export type MessageReceiptType = 'read' | 'read-self' | 'hist_sync' | 'peer_msg' | undefined +export type MessageReceiptType = 'read' | 'read-self' | 'hist_sync' | 'peer_msg' | 'sender' | undefined export type MediaConnInfo = { auth: string diff --git a/src/Utils/decode-wa-message.ts b/src/Utils/decode-wa-message.ts index 6aa7314..85b2a31 100644 --- a/src/Utils/decode-wa-message.ts +++ b/src/Utils/decode-wa-message.ts @@ -14,8 +14,8 @@ export const decodeMessageStanza = (stanza: BinaryNode, auth: AuthenticationStat let chatId: string let author: string - const msgId: string = stanza.attrs.id - const from: string = stanza.attrs.from + const msgId = stanza.attrs.id + const from = stanza.attrs.from const participant: string | undefined = stanza.attrs.participant const recipient: string | undefined = stanza.attrs.recipient @@ -83,6 +83,7 @@ export const decodeMessageStanza = (stanza: BinaryNode, auth: AuthenticationStat return { fullMessage, category: stanza.attrs.category, + author, decryptionTask: (async() => { let decryptables = 0 if(Array.isArray(stanza.content)) {