feat: handle call events

This commit is contained in:
Adhiraj Singh
2022-05-09 15:00:53 +05:30
parent 72aa8f9ea7
commit ae4aa67950
7 changed files with 119 additions and 11 deletions

View File

@@ -1,8 +1,8 @@
import { proto } from '../../WAProto'
import { KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT } from '../Defaults'
import { BaileysEventMap, MessageReceiptType, MessageUserReceipt, SocketConfig, WAMessageStubType } from '../Types'
import { debouncedTimeout, decodeMessageStanza, delay, encodeBigEndian, generateSignalPubKey, getNextPreKeys, getStatusFromReceiptType, normalizeMessageContent, xmppPreKey, xmppSignedPreKey } from '../Utils'
import { BaileysEventMap, MessageReceiptType, MessageUserReceipt, SocketConfig, WACallEvent, WAMessageStubType } from '../Types'
import { debouncedTimeout, decodeMessageStanza, delay, encodeBigEndian, generateSignalPubKey, getCallStatusFromNode, getNextPreKeys, getStatusFromReceiptType, normalizeMessageContent, unixTimestampSeconds, 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, isJidUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary'
@@ -42,6 +42,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
)
const msgRetryMap = config.msgRetryCounterMap || { }
const callOfferData: { [id: string]: WACallEvent } = { }
const historyCache = new Set<string>()
@@ -518,15 +519,43 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
})
ws.on('CB:call', async(node: BinaryNode) => {
logger.info({ node }, 'recv call')
const [child] = getAllBinaryNodeChildren(node)
if(!!child?.tag) {
sendMessageAck(node, { class: 'call', type: child.tag })
.catch(
error => onUnexpectedError(error, 'ack call')
)
const { attrs } = node
const [infoChild] = getAllBinaryNodeChildren(node)
const callId = infoChild.attrs['call-id']
const from = infoChild.attrs.from || infoChild.attrs['call-creator']
const status = getCallStatusFromNode(infoChild)
const call: WACallEvent = {
chatId: attrs.from,
from,
id: callId,
date: new Date(+attrs.t * 1000),
offline: !!attrs.offline,
status,
}
if(status === 'offer') {
call.isVideo = !!getBinaryNodeChild(infoChild, 'video')
call.isGroup = infoChild.attrs.type === 'group'
callOfferData[call.id] = call
}
// use existing call info to populate this event
if(callOfferData[call.id]) {
call.isVideo = callOfferData[call.id].isVideo
call.isGroup = callOfferData[call.id].isGroup
}
// delete data once call has ended
if(status === 'reject' || status === 'accept' || status === 'timeout') {
delete callOfferData[call.id]
}
ev.emit('call', [call])
await sendMessageAck(node, { class: 'call', type: infoChild.tag })
.catch(
error => onUnexpectedError(error, 'ack call')
)
})
ws.on('CB:receipt', node => {
@@ -552,6 +581,35 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
)
})
ev.on('call', ([ call ]) => {
// missed call + group call notification message generation
if(call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
const msg: proto.IWebMessageInfo = {
key: {
remoteJid: call.chatId,
id: call.id,
fromMe: false
},
messageTimestamp: unixTimestampSeconds(call.date),
}
if(call.status === 'timeout') {
if(call.isGroup) {
msg.messageStubType = call.isVideo ? WAMessageStubType.CALL_MISSED_GROUP_VIDEO : WAMessageStubType.CALL_MISSED_GROUP_VOICE
} else {
msg.messageStubType = call.isVideo ? WAMessageStubType.CALL_MISSED_VIDEO : WAMessageStubType.CALL_MISSED_VOICE
}
} else {
msg.message = { call: { callKey: Buffer.from(call.id) } }
}
const protoMsg = proto.WebMessageInfo.fromObject(msg)
ev.emit(
'messages.upsert',
{ messages: [protoMsg], type: call.offline ? 'append' : 'notify' }
)
}
})
return {
...sock,
processMessage: processMessageLocal,