feat: correctly send retry messages w count

This commit is contained in:
Adhiraj Singh
2022-07-13 10:34:13 +05:30
parent f5af502c19
commit 4c60e311f4
3 changed files with 34 additions and 18 deletions

View File

@@ -64,14 +64,16 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
const sendRetryRequest = async(node: BinaryNode) => { const sendRetryRequest = async(node: BinaryNode) => {
const msgId = node.attrs.id const msgId = node.attrs.id
const retryCount = msgRetryMap[msgId] || 1
let retryCount = msgRetryMap[msgId] || 0
if(retryCount >= 5) { if(retryCount >= 5) {
logger.debug({ retryCount, msgId }, 'reached retry limit, clearing') logger.debug({ retryCount, msgId }, 'reached retry limit, clearing')
delete msgRetryMap[msgId] delete msgRetryMap[msgId]
return return
} }
msgRetryMap[msgId] = retryCount + 1 retryCount += 1
msgRetryMap[msgId] = retryCount
const isGroup = !!node.attrs.participant const isGroup = !!node.attrs.participant
const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds
@@ -79,11 +81,6 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
const deviceIdentity = proto.ADVSignedDeviceIdentity.encode(account!).finish() const deviceIdentity = proto.ADVSignedDeviceIdentity.encode(account!).finish()
await authState.keys.transaction( await authState.keys.transaction(
async() => { async() => {
const { update, preKeys } = await getNextPreKeys(authState, 1)
const [keyId] = Object.keys(preKeys)
const key = preKeys[+keyId]
const decFrom = node.attrs.from ? jidDecode(node.attrs.from) : undefined const decFrom = node.attrs.from ? jidDecode(node.attrs.from) : undefined
const receipt: BinaryNode = { const receipt: BinaryNode = {
tag: 'receipt', tag: 'receipt',
@@ -119,6 +116,11 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
} }
if(retryCount > 1) { if(retryCount > 1) {
const { update, preKeys } = await getNextPreKeys(authState, 1)
const [keyId] = Object.keys(preKeys)
const key = preKeys[+keyId]
const exec = generateSignalPubKey(Buffer.from(KEY_BUNDLE_TYPE)).slice(0, 1) const exec = generateSignalPubKey(Buffer.from(KEY_BUNDLE_TYPE)).slice(0, 1)
const content = receipt.content! as BinaryNode[] const content = receipt.content! as BinaryNode[]
content.push({ content.push({
@@ -132,13 +134,13 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
{ tag: 'device-identity', attrs: { }, content: deviceIdentity } { tag: 'device-identity', attrs: { }, content: deviceIdentity }
] ]
}) })
ev.emit('creds.update', update)
} }
await sendNode(receipt) await sendNode(receipt)
logger.info({ msgAttrs: node.attrs, retryCount }, 'sent retry receipt') logger.info({ msgAttrs: node.attrs, retryCount }, 'sent retry receipt')
ev.emit('creds.update', update)
} }
) )
} }
@@ -268,7 +270,11 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
msgRetryMap[key] = (msgRetryMap[key] || 0) + 1 msgRetryMap[key] = (msgRetryMap[key] || 0) + 1
} }
const sendMessagesAgain = async(key: proto.IMessageKey, ids: string[]) => { const sendMessagesAgain = async(
key: proto.IMessageKey,
ids: string[],
retryNode: BinaryNode
) => {
const msgs = await Promise.all(ids.map(id => getMessage({ ...key, id }))) const msgs = await Promise.all(ids.map(id => getMessage({ ...key, id })))
const remoteJid = key.remoteJid! const remoteJid = key.remoteJid!
const participant = key.participant || remoteJid const participant = key.participant || remoteJid
@@ -293,7 +299,10 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
if(sendToAll) { if(sendToAll) {
msgRelayOpts.useUserDevicesCache = false msgRelayOpts.useUserDevicesCache = false
} else { } else {
msgRelayOpts.participant = participant msgRelayOpts.participant = {
jid: participant,
count: +retryNode.attrs.count
}
} }
await relayMessage(key.remoteJid!, msg, msgRelayOpts) await relayMessage(key.remoteJid!, msg, msgRelayOpts)
@@ -363,11 +372,12 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
if(attrs.type === 'retry') { if(attrs.type === 'retry') {
// correctly set who is asking for the retry // correctly set who is asking for the retry
key.participant = key.participant || attrs.from key.participant = key.participant || attrs.from
const retryNode = getBinaryNodeChild(node, 'retry')
if(willSendMessageAgain(ids[0], key.participant)) { if(willSendMessageAgain(ids[0], key.participant)) {
if(key.fromMe) { if(key.fromMe) {
try { try {
logger.debug({ attrs, key }, 'recv retry request') logger.debug({ attrs, key }, 'recv retry request')
await sendMessagesAgain(key, ids) await sendMessagesAgain(key, ids, retryNode!)
} catch(error) { } catch(error) {
logger.error({ key, ids, trace: error.stack }, 'error in sending message again') logger.error({ key, ids, trace: error.stack }, 'error in sending message again')
} }

View File

@@ -299,7 +299,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
additionalAttributes = { ...additionalAttributes, device_fanout: 'false' } additionalAttributes = { ...additionalAttributes, device_fanout: 'false' }
} }
const { user, device } = jidDecode(participant)! const { user, device } = jidDecode(participant.jid)!
devices.push({ user, device }) devices.push({ user, device })
} }
@@ -423,6 +423,12 @@ export const makeMessagesSocket = (config: SocketConfig) => {
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2 shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2
} }
if(participant?.count) {
for(const node of participants) {
node.attrs.count = participant.count.toString()
}
}
if(participants.length) { if(participants.length) {
binaryNodeContent.push({ binaryNodeContent.push({
tag: 'participants', tag: 'participants',
@@ -446,12 +452,12 @@ export const makeMessagesSocket = (config: SocketConfig) => {
if(participant) { if(participant) {
if(isJidGroup(destinationJid)) { if(isJidGroup(destinationJid)) {
stanza.attrs.to = destinationJid stanza.attrs.to = destinationJid
stanza.attrs.participant = participant stanza.attrs.participant = participant.jid
} else if(areJidsSameUser(participant, meId)) { } else if(areJidsSameUser(participant.jid, meId)) {
stanza.attrs.to = participant stanza.attrs.to = participant.jid
stanza.attrs.recipient = destinationJid stanza.attrs.recipient = destinationJid
} else { } else {
stanza.attrs.to = participant stanza.attrs.to = participant.jid
} }
} else { } else {
stanza.attrs.to = destinationJid stanza.attrs.to = destinationJid

View File

@@ -150,7 +150,7 @@ type MinimalRelayOptions = {
export type MessageRelayOptions = MinimalRelayOptions & { export type MessageRelayOptions = MinimalRelayOptions & {
/** only send to a specific participant; used when a message decryption fails for a single user */ /** only send to a specific participant; used when a message decryption fails for a single user */
participant?: string participant?: { jid: string, count: number }
/** additional attributes to add to the WA binary node */ /** additional attributes to add to the WA binary node */
additionalAttributes?: { [_: string]: string } additionalAttributes?: { [_: string]: string }
/** should we use the devices cache, or fetch afresh from the server; default assumed to be "true" */ /** should we use the devices cache, or fetch afresh from the server; default assumed to be "true" */