feat: ability to filter chats and messages

This commit is contained in:
Anton Voylenko 2025-09-02 23:19:46 +03:00
commit dd886a1fea
5 changed files with 274 additions and 29 deletions

View file

@ -1,6 +1,9 @@
const axios = require('axios')
const { globalApiKey, disabledCallbacks, enableWebHook } = require('./config')
const { logger } = require('./logger')
const ChatFactory = require('whatsapp-web.js/src/factories/ChatFactory')
const Client = require('whatsapp-web.js').Client
const { Chat, Message } = require('whatsapp-web.js/src/structures')
// Trigger webhook endpoint
const triggerWebhook = (webhookURL, sessionId, dataType, data) => {
@ -73,6 +76,103 @@ const exposeFunctionIfAbsent = async (page, name, fn) => {
await page.exposeFunction(name, fn)
}
const patchWWebLibrary = async (client) => {
// MUST be run after the 'ready' event fired
Client.prototype.getChats = async function (searchOptions = {}) {
const chats = await this.pupPage.evaluate(async (searchOptions) => {
return await window.WWebJS.getChats({ ...searchOptions })
}, searchOptions)
return chats.map(chat => ChatFactory.create(this, chat))
}
Chat.prototype.fetchMessages = async function (searchOptions) {
const messages = await this.client.pupPage.evaluate(async (chatId, searchOptions) => {
const msgFilter = (m) => {
if (m.isNotification) {
return false
}
if (searchOptions && searchOptions.fromMe !== undefined && m.id.fromMe !== searchOptions.fromMe) {
return false
}
if (searchOptions && searchOptions.since !== undefined && Number.isFinite(searchOptions.since) && m.t < searchOptions.since) {
return false
}
return true
}
const chat = await window.WWebJS.getChat(chatId, { getAsModel: false })
let msgs = chat.msgs.getModelsArray().filter(msgFilter)
if (searchOptions && searchOptions.limit > 0) {
while (msgs.length < searchOptions.limit) {
const loadedMessages = await window.Store.ConversationMsgs.loadEarlierMsgs(chat)
if (!loadedMessages || !loadedMessages.length) break
msgs = [...loadedMessages.filter(msgFilter), ...msgs]
}
if (msgs.length > searchOptions.limit) {
msgs.sort((a, b) => (a.t > b.t) ? 1 : -1)
msgs = msgs.splice(msgs.length - searchOptions.limit)
}
}
return msgs.map(m => window.WWebJS.getMessageModel(m))
}, this.id._serialized, searchOptions)
return messages.map(m => new Message(this.client, m))
}
await client.pupPage.evaluate(() => {
// hotfix for https://github.com/pedroslopez/whatsapp-web.js/pull/3643
window.WWebJS.getChats = async (searchOptions = {}) => {
const chatFilter = (c) => {
if (searchOptions && searchOptions.unread === true && c.unreadCount === 0) {
return false
}
if (searchOptions && searchOptions.since !== undefined && Number.isFinite(searchOptions.since) && c.t < searchOptions.since) {
return false
}
return true
}
const allChats = window.Store.Chat.getModelsArray()
const filteredChats = allChats.filter(chatFilter)
return await Promise.all(
filteredChats.map(chat => window.WWebJS.getChatModel(chat))
)
}
// hotfix for https://github.com/pedroslopez/whatsapp-web.js/pull/3703
window.Store.FindOrCreateChat = window.require('WAWebFindChatAction')
window.WWebJS.getChat = async (chatId, { getAsModel = true } = {}) => {
const isChannel = /@\w*newsletter\b/.test(chatId)
const chatWid = window.Store.WidFactory.createWid(chatId)
let chat
if (isChannel) {
try {
chat = window.Store.NewsletterCollection.get(chatId)
if (!chat) {
await window.Store.ChannelUtils.loadNewsletterPreviewChat(chatId)
chat = await window.Store.NewsletterCollection.find(chatWid)
}
} catch (err) {
chat = null
}
} else {
chat = window.Store.Chat.get(chatWid) || (await window.Store.FindOrCreateChat.findOrCreateLatestChat(chatWid))?.chat
}
return getAsModel && chat
? await window.WWebJS.getChatModel(chat, { isChannel })
: chat
}
})
}
module.exports = {
triggerWebhook,
sendErrorResponse,
@ -81,5 +181,6 @@ module.exports = {
sendMessageSeenStatus,
decodeBase64,
sleep,
exposeFunctionIfAbsent
exposeFunctionIfAbsent,
patchWWebLibrary
}