refactor: message decoding

1. removes redundant receipt (was exactly the same as delivery receipt without the timestamp)
2. decodeWAMessage now returns a proper message struct
3. each message stanza results in exactly one message decoded
This commit is contained in:
Adhiraj Singh
2022-01-06 23:27:14 +05:30
parent 0b5d772b08
commit 6a2cb5a413
3 changed files with 51 additions and 124 deletions

View File

@@ -1,15 +1,15 @@
import { Boom } from '@hapi/boom'
import { unpadRandomMax16 } from "./generics"
import { AuthenticationState } from "../Types"
import { areJidsSameUser, BinaryNode as BinaryNodeM, encodeBinaryNode, isJidBroadcast, isJidGroup, isJidStatusBroadcast, isJidUser } from '../WABinary'
import { WAMessageKey, AuthenticationState } from '../Types'
import { areJidsSameUser, BinaryNode, isJidBroadcast, isJidGroup, isJidStatusBroadcast, isJidUser, jidNormalizedUser } from '../WABinary'
import { decryptGroupSignalProto, decryptSignalProto, processSenderKeyMessage } from './signal'
import { proto } from '../../WAProto'
type MessageType = 'chat' | 'peer_broadcast' | 'other_broadcast' | 'group' | 'direct_peer_status' | 'other_status'
export const decodeMessageStanza = async(stanza: BinaryNodeM, auth: AuthenticationState) => {
const deviceIdentity = (stanza.content as BinaryNodeM[])?.find(m => m.tag === 'device-identity')
const deviceIdentityBytes = deviceIdentity ? deviceIdentity.content as Buffer : undefined
export const decodeMessageStanza = async(stanza: BinaryNode, auth: AuthenticationState) => {
//const deviceIdentity = (stanza.content as BinaryNodeM[])?.find(m => m.tag === 'device-identity')
//const deviceIdentityBytes = deviceIdentity ? deviceIdentity.content as Buffer : undefined
let msgType: MessageType
let chatId: string
@@ -53,18 +53,34 @@ export const decodeMessageStanza = async(stanza: BinaryNodeM, auth: Authenticati
chatId = from
author = participant
}
const sender = msgType === 'chat' ? author : chatId
const successes: proto.Message[] = []
const failures: { error: Boom }[] = []
const fromMe = isMe(participant || chatId)
const pushname = stanza.attrs.notify
const key: WAMessageKey = {
remoteJid: chatId,
fromMe,
id: msgId,
participant
}
const fullMessage: proto.IWebMessageInfo = {
key,
messageTimestamp: +stanza.attrs.t,
pushName: pushname,
status: key.fromMe ? proto.WebMessageInfo.WebMessageInfoStatus.SERVER_ACK : null,
}
if(Array.isArray(stanza.content)) {
for(const { tag, attrs, content } of stanza.content as BinaryNodeM[]) {
for(const { tag, attrs, content } of stanza.content) {
if(tag !== 'enc') continue
if(!Buffer.isBuffer(content) && !(content instanceof Uint8Array)) continue
if(!(content instanceof Uint8Array)) continue
let msgBuffer: Buffer
try {
let msgBuffer: Buffer
const e2eType = attrs.type
switch(e2eType) {
case 'skmsg':
@@ -76,28 +92,20 @@ export const decodeMessageStanza = async(stanza: BinaryNodeM, auth: Authenticati
msgBuffer = await decryptSignalProto(user, e2eType, content as Buffer, auth)
break
}
const msg = proto.Message.decode(unpadRandomMax16(msgBuffer))
let msg: proto.IMessage = proto.Message.decode(unpadRandomMax16(msgBuffer))
msg = msg.deviceSentMessage?.message || msg
if(msg.senderKeyDistributionMessage) {
await processSenderKeyMessage(author, msg.senderKeyDistributionMessage, auth)
}
successes.push(msg)
if(fullMessage.message) Object.assign(fullMessage.message, msg)
else fullMessage.message = msg
} catch(error) {
failures.push({ error: new Boom(error, { data: Buffer.from(encodeBinaryNode(stanza)).toString('base64') }) })
fullMessage.messageStubType = proto.WebMessageInfo.WebMessageInfoStubType.CIPHERTEXT
fullMessage.messageStubParameters = [error.message]
}
}
}
return {
msgId,
chatId,
author,
from,
timestamp: +stanza.attrs.t,
participant,
recipient,
pushname: stanza.attrs.notify,
successes,
failures
}
return fullMessage
}