refactor: cleanup and add browser args

This commit is contained in:
Anton Voylenko 2025-06-12 13:45:58 +03:00
commit 725af66600
2 changed files with 202 additions and 189 deletions

View file

@ -3,7 +3,7 @@ const fs = require('fs')
const path = require('path') const path = require('path')
const sessions = new Map() const sessions = new Map()
const { baseWebhookURL, sessionFolderPath, maxAttachmentSize, setMessagesAsSeen, webVersion, webVersionCacheType, recoverSessions, chromeBin, headless, releaseBrowserLock } = require('./config') const { baseWebhookURL, sessionFolderPath, maxAttachmentSize, setMessagesAsSeen, webVersion, webVersionCacheType, recoverSessions, chromeBin, headless, releaseBrowserLock } = require('./config')
const { triggerWebhook, waitForNestedObject, checkIfEventisEnabled, sendMessageSeenStatus } = require('./utils') const { triggerWebhook, waitForNestedObject, isEventEnabled, sendMessageSeenStatus, sleep } = require('./utils')
const { logger } = require('./logger') const { logger } = require('./logger')
const { initWebSocketServer, terminateWebSocketServer, triggerWebSocket } = require('./websocket') const { initWebSocketServer, terminateWebSocketServer, triggerWebSocket } = require('./websocket')
@ -74,7 +74,7 @@ const restoreSessions = () => {
const match = file.match(/^session-(.+)$/) const match = file.match(/^session-(.+)$/)
if (match) { if (match) {
const sessionId = match[1] const sessionId = match[1]
logger.warn({ sessionId }, 'existing session detected') logger.warn({ sessionId }, 'Existing session detected')
await setupSession(sessionId) await setupSession(sessionId)
} }
} }
@ -90,7 +90,7 @@ const setupSession = async (sessionId) => {
if (sessions.has(sessionId)) { if (sessions.has(sessionId)) {
return { success: false, message: `Session already exists for: ${sessionId}`, client: sessions.get(sessionId) } return { success: false, message: `Session already exists for: ${sessionId}`, client: sessions.get(sessionId) }
} }
logger.info({ sessionId }, 'Session is being initiated')
// Disable the delete folder from the logout function (will be handled separately) // Disable the delete folder from the logout function (will be handled separately)
const localAuth = new LocalAuth({ clientId: sessionId, dataPath: sessionFolderPath }) const localAuth = new LocalAuth({ clientId: sessionId, dataPath: sessionFolderPath })
delete localAuth.logout delete localAuth.logout
@ -100,7 +100,46 @@ const setupSession = async (sessionId) => {
puppeteer: { puppeteer: {
executablePath: chromeBin, executablePath: chromeBin,
headless, headless,
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu', '--disable-dev-shm-usage'] args: [
'--autoplay-policy=user-gesture-required',
'--disable-background-networking',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-breakpad',
'--disable-client-side-phishing-detection',
'--disable-component-update',
'--disable-default-apps',
'--disable-dev-shm-usage',
'--disable-domain-reliability',
'--disable-extensions',
'--disable-features=AudioServiceOutOfProcess',
'--disable-hang-monitor',
'--disable-ipc-flooding-protection',
'--disable-notifications',
'--disable-offer-store-unmasked-wallet-cards',
'--disable-popup-blocking',
'--disable-print-preview',
'--disable-prompt-on-repost',
'--disable-renderer-backgrounding',
'--disable-speech-api',
'--disable-sync',
'--disable-gpu',
'--disable-accelerated-2d-canvas',
'--hide-scrollbars',
'--ignore-gpu-blacklist',
'--metrics-recording-only',
'--mute-audio',
'--no-default-browser-check',
'--no-first-run',
'--no-pings',
'--no-zygote',
'--password-store=basic',
'--use-gl=swiftshader',
'--use-mock-keychain',
'--disable-setuid-sandbox',
'--no-sandbox',
'--disable-blink-features=AutomationControlled'
]
}, },
authStrategy: localAuth authStrategy: localAuth
} }
@ -179,186 +218,162 @@ const initializeEvents = (client, sessionId) => {
}).catch(e => { }) }).catch(e => { })
} }
checkIfEventisEnabled('auth_failure') if (isEventEnabled('auth_failure')) {
.then(_ => {
client.on('auth_failure', (msg) => { client.on('auth_failure', (msg) => {
triggerWebhook(sessionWebhook, sessionId, 'status', { msg }) triggerWebhook(sessionWebhook, sessionId, 'status', { msg })
triggerWebSocket(sessionId, 'status', { msg }) triggerWebSocket(sessionId, 'status', { msg })
}) })
}) }
checkIfEventisEnabled('authenticated') if (isEventEnabled('authenticated')) {
.then(_ => {
client.qr = null client.qr = null
client.on('authenticated', () => { client.on('authenticated', () => {
triggerWebhook(sessionWebhook, sessionId, 'authenticated') triggerWebhook(sessionWebhook, sessionId, 'authenticated')
triggerWebSocket(sessionId, 'authenticated') triggerWebSocket(sessionId, 'authenticated')
}) })
}) }
checkIfEventisEnabled('call') if (isEventEnabled('call')) {
.then(_ => { client.on('call', (call) => {
client.on('call', async (call) => {
triggerWebhook(sessionWebhook, sessionId, 'call', { call }) triggerWebhook(sessionWebhook, sessionId, 'call', { call })
triggerWebSocket(sessionId, 'call', { call }) triggerWebSocket(sessionId, 'call', { call })
}) })
}) }
checkIfEventisEnabled('change_state') if (isEventEnabled('change_state')) {
.then(_ => {
client.on('change_state', state => { client.on('change_state', state => {
triggerWebhook(sessionWebhook, sessionId, 'change_state', { state }) triggerWebhook(sessionWebhook, sessionId, 'change_state', { state })
triggerWebSocket(sessionId, 'change_state', { state }) triggerWebSocket(sessionId, 'change_state', { state })
}) })
}) }
checkIfEventisEnabled('disconnected') if (isEventEnabled('disconnected')) {
.then(_ => {
client.on('disconnected', (reason) => { client.on('disconnected', (reason) => {
triggerWebhook(sessionWebhook, sessionId, 'disconnected', { reason }) triggerWebhook(sessionWebhook, sessionId, 'disconnected', { reason })
triggerWebSocket(sessionId, 'disconnected', { reason }) triggerWebSocket(sessionId, 'disconnected', { reason })
}) })
}) }
checkIfEventisEnabled('group_join') if (isEventEnabled('group_join')) {
.then(_ => {
client.on('group_join', (notification) => { client.on('group_join', (notification) => {
triggerWebhook(sessionWebhook, sessionId, 'group_join', { notification }) triggerWebhook(sessionWebhook, sessionId, 'group_join', { notification })
triggerWebSocket(sessionId, 'group_join', { notification }) triggerWebSocket(sessionId, 'group_join', { notification })
}) })
}) }
checkIfEventisEnabled('group_leave') if (isEventEnabled('group_leave')) {
.then(_ => {
client.on('group_leave', (notification) => { client.on('group_leave', (notification) => {
triggerWebhook(sessionWebhook, sessionId, 'group_leave', { notification }) triggerWebhook(sessionWebhook, sessionId, 'group_leave', { notification })
triggerWebSocket(sessionId, 'group_leave', { notification }) triggerWebSocket(sessionId, 'group_leave', { notification })
}) })
}) }
checkIfEventisEnabled('group_admin_changed') if (isEventEnabled('group_admin_changed')) {
.then(_ => {
client.on('group_admin_changed', (notification) => { client.on('group_admin_changed', (notification) => {
triggerWebhook(sessionWebhook, sessionId, 'group_admin_changed', { notification }) triggerWebhook(sessionWebhook, sessionId, 'group_admin_changed', { notification })
triggerWebSocket(sessionId, 'group_admin_changed', { notification }) triggerWebSocket(sessionId, 'group_admin_changed', { notification })
}) })
}) }
checkIfEventisEnabled('group_membership_request') if (isEventEnabled('group_membership_request')) {
.then(_ => {
client.on('group_membership_request', (notification) => { client.on('group_membership_request', (notification) => {
triggerWebhook(sessionWebhook, sessionId, 'group_membership_request', { notification }) triggerWebhook(sessionWebhook, sessionId, 'group_membership_request', { notification })
triggerWebSocket(sessionId, 'group_membership_request', { notification }) triggerWebSocket(sessionId, 'group_membership_request', { notification })
}) })
}) }
checkIfEventisEnabled('group_update') if (isEventEnabled('group_update')) {
.then(_ => {
client.on('group_update', (notification) => { client.on('group_update', (notification) => {
triggerWebhook(sessionWebhook, sessionId, 'group_update', { notification }) triggerWebhook(sessionWebhook, sessionId, 'group_update', { notification })
triggerWebSocket(sessionId, 'group_update', { notification }) triggerWebSocket(sessionId, 'group_update', { notification })
}) })
}) }
checkIfEventisEnabled('loading_screen') if (isEventEnabled('loading_screen')) {
.then(_ => {
client.on('loading_screen', (percent, message) => { client.on('loading_screen', (percent, message) => {
triggerWebhook(sessionWebhook, sessionId, 'loading_screen', { percent, message }) triggerWebhook(sessionWebhook, sessionId, 'loading_screen', { percent, message })
triggerWebSocket(sessionId, 'loading_screen', { percent, message }) triggerWebSocket(sessionId, 'loading_screen', { percent, message })
}) })
}) }
checkIfEventisEnabled('media_uploaded') if (isEventEnabled('media_uploaded')) {
.then(_ => {
client.on('media_uploaded', (message) => { client.on('media_uploaded', (message) => {
triggerWebhook(sessionWebhook, sessionId, 'media_uploaded', { message }) triggerWebhook(sessionWebhook, sessionId, 'media_uploaded', { message })
triggerWebSocket(sessionId, 'media_uploaded', { message }) triggerWebSocket(sessionId, 'media_uploaded', { message })
}) })
}) }
checkIfEventisEnabled('message')
.then(_ => {
client.on('message', async (message) => { client.on('message', async (message) => {
if (isEventEnabled('message')) {
triggerWebhook(sessionWebhook, sessionId, 'message', { message }) triggerWebhook(sessionWebhook, sessionId, 'message', { message })
triggerWebSocket(sessionId, 'message', { message }) triggerWebSocket(sessionId, 'message', { message })
if (message.hasMedia && message._data?.size < maxAttachmentSize) { if (message.hasMedia && message._data?.size < maxAttachmentSize) {
// custom service event // custom service event
checkIfEventisEnabled('media').then(_ => { if (isEventEnabled('media')) {
message.downloadMedia().then(messageMedia => { message.downloadMedia().then(messageMedia => {
triggerWebhook(sessionWebhook, sessionId, 'media', { messageMedia, message }) triggerWebhook(sessionWebhook, sessionId, 'media', { messageMedia, message })
triggerWebSocket(sessionId, 'media', { messageMedia, message }) triggerWebSocket(sessionId, 'media', { messageMedia, message })
}).catch(error => { }).catch(error => {
logger.error({ sessionId, err: error }, 'Failed to download media') logger.error({ sessionId, err: error }, 'Failed to download media')
}) })
}) }
}
} }
if (setMessagesAsSeen) { if (setMessagesAsSeen) {
// small delay to ensure the message is processed before sending seen status
await sleep(1000)
sendMessageSeenStatus(message) sendMessageSeenStatus(message)
} }
}) })
})
checkIfEventisEnabled('message_ack') if (isEventEnabled('message_ack')) {
.then(_ => { client.on('message_ack', (message, ack) => {
client.on('message_ack', async (message, ack) => {
triggerWebhook(sessionWebhook, sessionId, 'message_ack', { message, ack }) triggerWebhook(sessionWebhook, sessionId, 'message_ack', { message, ack })
triggerWebSocket(sessionId, 'message_ack', { message, ack }) triggerWebSocket(sessionId, 'message_ack', { message, ack })
if (setMessagesAsSeen) { })
sendMessageSeenStatus(message)
} }
})
})
checkIfEventisEnabled('message_create') if (isEventEnabled('message_create')) {
.then(_ => { client.on('message_create', (message) => {
client.on('message_create', async (message) => {
triggerWebhook(sessionWebhook, sessionId, 'message_create', { message }) triggerWebhook(sessionWebhook, sessionId, 'message_create', { message })
triggerWebSocket(sessionId, 'message_create', { message }) triggerWebSocket(sessionId, 'message_create', { message })
if (setMessagesAsSeen) { })
sendMessageSeenStatus(message)
} }
})
})
checkIfEventisEnabled('message_reaction') if (isEventEnabled('message_reaction')) {
.then(_ => {
client.on('message_reaction', (reaction) => { client.on('message_reaction', (reaction) => {
triggerWebhook(sessionWebhook, sessionId, 'message_reaction', { reaction }) triggerWebhook(sessionWebhook, sessionId, 'message_reaction', { reaction })
triggerWebSocket(sessionId, 'message_reaction', { reaction }) triggerWebSocket(sessionId, 'message_reaction', { reaction })
}) })
}) }
checkIfEventisEnabled('message_edit') if (isEventEnabled('message_edit')) {
.then(_ => {
client.on('message_edit', (message, newBody, prevBody) => { client.on('message_edit', (message, newBody, prevBody) => {
triggerWebhook(sessionWebhook, sessionId, 'message_edit', { message, newBody, prevBody }) triggerWebhook(sessionWebhook, sessionId, 'message_edit', { message, newBody, prevBody })
triggerWebSocket(sessionId, 'message_edit', { message, newBody, prevBody }) triggerWebSocket(sessionId, 'message_edit', { message, newBody, prevBody })
}) })
}) }
checkIfEventisEnabled('message_ciphertext') if (isEventEnabled('message_ciphertext')) {
.then(_ => {
client.on('message_ciphertext', (message) => { client.on('message_ciphertext', (message) => {
triggerWebhook(sessionWebhook, sessionId, 'message_ciphertext', { message }) triggerWebhook(sessionWebhook, sessionId, 'message_ciphertext', { message })
triggerWebSocket(sessionId, 'message_ciphertext', { message }) triggerWebSocket(sessionId, 'message_ciphertext', { message })
}) })
}) }
checkIfEventisEnabled('message_revoke_everyone') if (isEventEnabled('message_revoke_everyone')) {
.then(_ => { client.on('message_revoke_everyone', (message) => {
client.on('message_revoke_everyone', async (message) => {
triggerWebhook(sessionWebhook, sessionId, 'message_revoke_everyone', { message }) triggerWebhook(sessionWebhook, sessionId, 'message_revoke_everyone', { message })
triggerWebSocket(sessionId, 'message_revoke_everyone', { message }) triggerWebSocket(sessionId, 'message_revoke_everyone', { message })
}) })
}) }
checkIfEventisEnabled('message_revoke_me') if (isEventEnabled('message_revoke_me')) {
.then(_ => { client.on('message_revoke_me', (message, revokedMsg) => {
client.on('message_revoke_me', async (message, revokedMsg) => {
triggerWebhook(sessionWebhook, sessionId, 'message_revoke_me', { message, revokedMsg }) triggerWebhook(sessionWebhook, sessionId, 'message_revoke_me', { message, revokedMsg })
triggerWebSocket(sessionId, 'message_revoke_me', { message, revokedMsg }) triggerWebSocket(sessionId, 'message_revoke_me', { message, revokedMsg })
}) })
}) }
client.on('qr', (qr) => { client.on('qr', (qr) => {
// by default QR code is being updated every 20 seconds // by default QR code is being updated every 20 seconds
@ -373,60 +388,53 @@ const initializeEvents = (client, sessionId) => {
client.qr = null client.qr = null
} }
}, 30000) }, 30000)
checkIfEventisEnabled('qr') if (isEventEnabled('qr')) {
.then(_ => {
triggerWebhook(sessionWebhook, sessionId, 'qr', { qr }) triggerWebhook(sessionWebhook, sessionId, 'qr', { qr })
triggerWebSocket(sessionId, 'qr', { qr }) triggerWebSocket(sessionId, 'qr', { qr })
}) }
}) })
checkIfEventisEnabled('ready') if (isEventEnabled('ready')) {
.then(_ => {
client.on('ready', () => { client.on('ready', () => {
triggerWebhook(sessionWebhook, sessionId, 'ready') triggerWebhook(sessionWebhook, sessionId, 'ready')
triggerWebSocket(sessionId, 'ready') triggerWebSocket(sessionId, 'ready')
}) })
}) }
checkIfEventisEnabled('contact_changed') if (isEventEnabled('contact_changed')) {
.then(_ => { client.on('contact_changed', (message, oldId, newId, isContact) => {
client.on('contact_changed', async (message, oldId, newId, isContact) => {
triggerWebhook(sessionWebhook, sessionId, 'contact_changed', { message, oldId, newId, isContact }) triggerWebhook(sessionWebhook, sessionId, 'contact_changed', { message, oldId, newId, isContact })
triggerWebSocket(sessionId, 'contact_changed', { message, oldId, newId, isContact }) triggerWebSocket(sessionId, 'contact_changed', { message, oldId, newId, isContact })
}) })
}) }
checkIfEventisEnabled('chat_removed') if (isEventEnabled('chat_removed')) {
.then(_ => { client.on('chat_removed', (chat) => {
client.on('chat_removed', async (chat) => {
triggerWebhook(sessionWebhook, sessionId, 'chat_removed', { chat }) triggerWebhook(sessionWebhook, sessionId, 'chat_removed', { chat })
triggerWebSocket(sessionId, 'chat_removed', { chat }) triggerWebSocket(sessionId, 'chat_removed', { chat })
}) })
}) }
checkIfEventisEnabled('chat_archived') if (isEventEnabled('chat_archived')) {
.then(_ => { client.on('chat_archived', (chat, currState, prevState) => {
client.on('chat_archived', async (chat, currState, prevState) => {
triggerWebhook(sessionWebhook, sessionId, 'chat_archived', { chat, currState, prevState }) triggerWebhook(sessionWebhook, sessionId, 'chat_archived', { chat, currState, prevState })
triggerWebSocket(sessionId, 'chat_archived', { chat, currState, prevState }) triggerWebSocket(sessionId, 'chat_archived', { chat, currState, prevState })
}) })
}) }
checkIfEventisEnabled('unread_count') if (isEventEnabled('unread_count')) {
.then(_ => { client.on('unread_count', (chat) => {
client.on('unread_count', async (chat) => {
triggerWebhook(sessionWebhook, sessionId, 'unread_count', { chat }) triggerWebhook(sessionWebhook, sessionId, 'unread_count', { chat })
triggerWebSocket(sessionId, 'unread_count', { chat }) triggerWebSocket(sessionId, 'unread_count', { chat })
}) })
}) }
checkIfEventisEnabled('vote_update') if (isEventEnabled('vote_update')) {
.then(_ => { client.on('vote_update', (vote) => {
client.on('vote_update', async (vote) => {
triggerWebhook(sessionWebhook, sessionId, 'vote_update', { vote }) triggerWebhook(sessionWebhook, sessionId, 'vote_update', { vote })
triggerWebSocket(sessionId, 'vote_update', { vote }) triggerWebSocket(sessionId, 'vote_update', { vote })
}) })
}) }
} }
// Function to delete client session folder // Function to delete client session folder

View file

@ -38,8 +38,8 @@ const waitForNestedObject = (rootObj, nestedPath, maxWaitTime = 10000, interval
}) })
} }
const checkIfEventisEnabled = (event) => { const isEventEnabled = (event) => {
return new Promise((resolve) => { if (!disabledCallbacks.includes(event)) { resolve() } }) return !disabledCallbacks.includes(event)
} }
const sendMessageSeenStatus = async (message) => { const sendMessageSeenStatus = async (message) => {
@ -59,11 +59,16 @@ const decodeBase64 = function * (base64String) {
} }
} }
const sleep = function (ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
module.exports = { module.exports = {
triggerWebhook, triggerWebhook,
sendErrorResponse, sendErrorResponse,
waitForNestedObject, waitForNestedObject,
checkIfEventisEnabled, isEventEnabled,
sendMessageSeenStatus, sendMessageSeenStatus,
decodeBase64 decodeBase64,
sleep
} }