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
This commit is contained in:
Adhiraj Singh
2022-04-03 11:27:13 +05:30
parent 64bab02b7c
commit 59f834ca39
4 changed files with 35 additions and 21 deletions

View File

@@ -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!)

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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)) {