feat: handle delete events accurately

This commit is contained in:
Adhiraj Singh
2022-07-06 22:05:00 +05:30
parent 41ca76a0af
commit d143ef0b7d
2 changed files with 62 additions and 17 deletions

View File

@@ -1,22 +1,23 @@
import EventEmitter from 'events'
import { proto } from '../../WAProto' import { proto } from '../../WAProto'
import { BaileysEventEmitter, Chat, WAMessageKey, WAMessageStatus, WAMessageStubType, WAMessageUpdate } from '../Types' import { Chat, WAMessageKey, WAMessageStatus, WAMessageStubType, WAMessageUpdate } from '../Types'
import { delay, generateMessageID, makeEventBuffer, toNumber, unixTimestampSeconds } from '../Utils' import { delay, generateMessageID, makeEventBuffer, toNumber, unixTimestampSeconds } from '../Utils'
import logger from '../Utils/logger' import logger from '../Utils/logger'
import { randomJid } from './utils' import { randomJid } from './utils'
describe('Event Buffer Tests', () => { describe('Event Buffer Tests', () => {
const emitter = new EventEmitter() as BaileysEventEmitter let ev: ReturnType<typeof makeEventBuffer>
const ev = makeEventBuffer(emitter, logger) beforeEach(() => {
ev = makeEventBuffer(logger)
})
it('should buffer a chat upsert & update event', async() => { it('should buffer a chat upsert & update event', async() => {
const chatId = randomJid() const chatId = randomJid()
const chats: Chat[] = [] const chats: Chat[] = []
emitter.on('chats.upsert', c => chats.push(...c)) ev.on('chats.upsert', c => chats.push(...c))
emitter.on('chats.update', () => fail('should not emit update event')) ev.on('chats.update', () => fail('should not emit update event'))
ev.buffer() ev.buffer()
ev.processInBuffer((async() => { ev.processInBuffer((async() => {
@@ -35,6 +36,41 @@ describe('Event Buffer Tests', () => {
expect(chats[0].unreadCount).toEqual(2) expect(chats[0].unreadCount).toEqual(2)
}) })
it('should overwrite a chats.delete event', async() => {
const chatId = randomJid()
const chats: Partial<Chat>[] = []
ev.on('chats.update', c => chats.push(...c))
ev.on('chats.delete', () => fail('not should have emitted'))
ev.buffer()
ev.emit('chats.update', [{ id: chatId, conversationTimestamp: 123, unreadCount: 1 }])
ev.emit('chats.delete', [chatId])
ev.emit('chats.update', [{ id: chatId, conversationTimestamp: 124, unreadCount: 1 }])
await ev.flush()
expect(chats).toHaveLength(1)
})
it('should overwrite a chats.update event', async() => {
const chatId = randomJid()
const chatsDeleted: string[] = []
ev.on('chats.delete', c => chatsDeleted.push(...c))
ev.on('chats.update', () => fail('not should have emitted'))
ev.buffer()
ev.emit('chats.update', [{ id: chatId, conversationTimestamp: 123, unreadCount: 1 }])
ev.emit('chats.delete', [chatId])
await ev.flush()
expect(chatsDeleted).toHaveLength(1)
})
it('should buffer message upsert events', async() => { it('should buffer message upsert events', async() => {
const messageTimestamp = unixTimestampSeconds() const messageTimestamp = unixTimestampSeconds()
const msg: proto.IWebMessageInfo = { const msg: proto.IWebMessageInfo = {
@@ -49,7 +85,7 @@ describe('Event Buffer Tests', () => {
const msgs: proto.IWebMessageInfo[] = [] const msgs: proto.IWebMessageInfo[] = []
emitter.on('messages.upsert', c => { ev.on('messages.upsert', c => {
msgs.push(...c.messages) msgs.push(...c.messages)
expect(c.type).toEqual('notify') expect(c.type).toEqual('notify')
}) })
@@ -67,7 +103,7 @@ describe('Event Buffer Tests', () => {
expect(msgs).toHaveLength(1) expect(msgs).toHaveLength(1)
expect(msgs[0].message).toBeTruthy() expect(msgs[0].message).toBeTruthy()
expect(toNumber(msgs[0].messageTimestamp)).toEqual(messageTimestamp) expect(toNumber(msgs[0].messageTimestamp!)).toEqual(messageTimestamp)
expect(msgs[0].status).toEqual(WAMessageStatus.READ) expect(msgs[0].status).toEqual(WAMessageStatus.READ)
}) })
@@ -84,8 +120,8 @@ describe('Event Buffer Tests', () => {
const msgs: proto.IWebMessageInfo[] = [] const msgs: proto.IWebMessageInfo[] = []
emitter.on('messages.upsert', c => msgs.push(...c.messages)) ev.on('messages.upsert', c => msgs.push(...c.messages))
emitter.on('message-receipt.update', () => fail('should not emit')) ev.on('message-receipt.update', () => fail('should not emit'))
ev.buffer() ev.buffer()
ev.emit('messages.upsert', { messages: [proto.WebMessageInfo.fromObject(msg)], type: 'notify' }) ev.emit('messages.upsert', { messages: [proto.WebMessageInfo.fromObject(msg)], type: 'notify' })
@@ -114,7 +150,7 @@ describe('Event Buffer Tests', () => {
const msgs: WAMessageUpdate[] = [] const msgs: WAMessageUpdate[] = []
emitter.on('messages.update', c => msgs.push(...c)) ev.on('messages.update', c => msgs.push(...c))
ev.buffer() ev.buffer()
ev.emit('messages.update', [{ key, update: { status: WAMessageStatus.DELIVERY_ACK } }]) ev.emit('messages.update', [{ key, update: { status: WAMessageStatus.DELIVERY_ACK } }])
@@ -141,11 +177,11 @@ describe('Event Buffer Tests', () => {
const chats: Partial<Chat>[] = [] const chats: Partial<Chat>[] = []
emitter.on('chats.update', c => chats.push(...c)) ev.on('chats.update', c => chats.push(...c))
ev.buffer() ev.buffer()
ev.emit('messages.upsert', { messages: [proto.WebMessageInfo.fromObject(msg)], type: 'notify' }) ev.emit('messages.upsert', { messages: [proto.WebMessageInfo.fromObject(msg)], type: 'notify' })
ev.emit('chats.update', [{ id: msg.key.remoteJid, unreadCount: 1, conversationTimestamp: msg.messageTimestamp }]) ev.emit('chats.update', [{ id: msg.key.remoteJid!, unreadCount: 1, conversationTimestamp: msg.messageTimestamp }])
ev.emit('messages.update', [{ key: msg.key, update: { status: WAMessageStatus.READ } }]) ev.emit('messages.update', [{ key: msg.key, update: { status: WAMessageStatus.READ } }])
await ev.flush() await ev.flush()

View File

@@ -150,18 +150,27 @@ function append<E extends BufferableEvent>(
delete data.chatUpdates[chat.id] delete data.chatUpdates[chat.id]
} }
if(data.chatDeletes.has(chat.id)) {
data.chatDeletes.delete(chat.id)
}
data.chatUpserts[chat.id] = upsert data.chatUpserts[chat.id] = upsert
} }
break break
case 'chats.update': case 'chats.update':
for(const update of eventData as Partial<Chat>[]) { for(const update of eventData as Partial<Chat>[]) {
const upsert = data.chatUpserts[update.id!] const chatId = update.id!
const upsert = data.chatUpserts[chatId]
if(upsert) { if(upsert) {
concatChats(upsert, update) concatChats(upsert, update)
} else { } else {
const chatUpdate = data.chatUpdates[update.id] || { } const chatUpdate = data.chatUpdates[chatId] || { }
data.chatUpdates[update.id] = concatChats(chatUpdate, update) data.chatUpdates[chatId] = concatChats(chatUpdate, update)
}
if(data.chatDeletes.has(chatId)) {
data.chatDeletes.delete(chatId)
} }
} }
@@ -315,7 +324,7 @@ function append<E extends BufferableEvent>(
if( if(
isRealMessage(message) isRealMessage(message)
&& shouldIncrementChatUnread(message) && shouldIncrementChatUnread(message)
&& typeof chat.unreadCount !== 'undefined' && typeof chat?.unreadCount !== 'undefined'
&& chat.unreadCount > 0 && chat.unreadCount > 0
) { ) {
logger.debug({ chatId: chat.id }, 'decrementing chat counter') logger.debug({ chatId: chat.id }, 'decrementing chat counter')