diff --git a/src/sessions.js b/src/sessions.js index 2b45dfc..625458d 100644 --- a/src/sessions.js +++ b/src/sessions.js @@ -3,7 +3,7 @@ const fs = require('fs') const path = require('path') const sessions = new Map() 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 { initWebSocketServer, terminateWebSocketServer, triggerWebSocket } = require('./websocket') @@ -74,7 +74,7 @@ const restoreSessions = () => { const match = file.match(/^session-(.+)$/) if (match) { const sessionId = match[1] - logger.warn({ sessionId }, 'existing session detected') + logger.warn({ sessionId }, 'Existing session detected') await setupSession(sessionId) } } @@ -90,7 +90,7 @@ const setupSession = async (sessionId) => { if (sessions.has(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) const localAuth = new LocalAuth({ clientId: sessionId, dataPath: sessionFolderPath }) delete localAuth.logout @@ -100,7 +100,46 @@ const setupSession = async (sessionId) => { puppeteer: { executablePath: chromeBin, 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 } @@ -179,186 +218,162 @@ const initializeEvents = (client, sessionId) => { }).catch(e => { }) } - checkIfEventisEnabled('auth_failure') - .then(_ => { - client.on('auth_failure', (msg) => { - triggerWebhook(sessionWebhook, sessionId, 'status', { msg }) - triggerWebSocket(sessionId, 'status', { msg }) - }) + if (isEventEnabled('auth_failure')) { + client.on('auth_failure', (msg) => { + triggerWebhook(sessionWebhook, sessionId, 'status', { msg }) + triggerWebSocket(sessionId, 'status', { msg }) }) + } - checkIfEventisEnabled('authenticated') - .then(_ => { - client.qr = null - client.on('authenticated', () => { - triggerWebhook(sessionWebhook, sessionId, 'authenticated') - triggerWebSocket(sessionId, 'authenticated') - }) + if (isEventEnabled('authenticated')) { + client.qr = null + client.on('authenticated', () => { + triggerWebhook(sessionWebhook, sessionId, 'authenticated') + triggerWebSocket(sessionId, 'authenticated') }) + } - checkIfEventisEnabled('call') - .then(_ => { - client.on('call', async (call) => { - triggerWebhook(sessionWebhook, sessionId, 'call', { call }) - triggerWebSocket(sessionId, 'call', { call }) - }) + if (isEventEnabled('call')) { + client.on('call', (call) => { + triggerWebhook(sessionWebhook, sessionId, 'call', { call }) + triggerWebSocket(sessionId, 'call', { call }) }) + } - checkIfEventisEnabled('change_state') - .then(_ => { - client.on('change_state', state => { - triggerWebhook(sessionWebhook, sessionId, 'change_state', { state }) - triggerWebSocket(sessionId, 'change_state', { state }) - }) + if (isEventEnabled('change_state')) { + client.on('change_state', state => { + triggerWebhook(sessionWebhook, sessionId, 'change_state', { state }) + triggerWebSocket(sessionId, 'change_state', { state }) }) + } - checkIfEventisEnabled('disconnected') - .then(_ => { - client.on('disconnected', (reason) => { - triggerWebhook(sessionWebhook, sessionId, 'disconnected', { reason }) - triggerWebSocket(sessionId, 'disconnected', { reason }) - }) + if (isEventEnabled('disconnected')) { + client.on('disconnected', (reason) => { + triggerWebhook(sessionWebhook, sessionId, 'disconnected', { reason }) + triggerWebSocket(sessionId, 'disconnected', { reason }) }) + } - checkIfEventisEnabled('group_join') - .then(_ => { - client.on('group_join', (notification) => { - triggerWebhook(sessionWebhook, sessionId, 'group_join', { notification }) - triggerWebSocket(sessionId, 'group_join', { notification }) - }) + if (isEventEnabled('group_join')) { + client.on('group_join', (notification) => { + triggerWebhook(sessionWebhook, sessionId, 'group_join', { notification }) + triggerWebSocket(sessionId, 'group_join', { notification }) }) + } - checkIfEventisEnabled('group_leave') - .then(_ => { - client.on('group_leave', (notification) => { - triggerWebhook(sessionWebhook, sessionId, 'group_leave', { notification }) - triggerWebSocket(sessionId, 'group_leave', { notification }) - }) + if (isEventEnabled('group_leave')) { + client.on('group_leave', (notification) => { + triggerWebhook(sessionWebhook, sessionId, 'group_leave', { notification }) + triggerWebSocket(sessionId, 'group_leave', { notification }) }) + } - checkIfEventisEnabled('group_admin_changed') - .then(_ => { - client.on('group_admin_changed', (notification) => { - triggerWebhook(sessionWebhook, sessionId, 'group_admin_changed', { notification }) - triggerWebSocket(sessionId, 'group_admin_changed', { notification }) - }) + if (isEventEnabled('group_admin_changed')) { + client.on('group_admin_changed', (notification) => { + triggerWebhook(sessionWebhook, sessionId, 'group_admin_changed', { notification }) + triggerWebSocket(sessionId, 'group_admin_changed', { notification }) }) + } - checkIfEventisEnabled('group_membership_request') - .then(_ => { - client.on('group_membership_request', (notification) => { - triggerWebhook(sessionWebhook, sessionId, 'group_membership_request', { notification }) - triggerWebSocket(sessionId, 'group_membership_request', { notification }) - }) + if (isEventEnabled('group_membership_request')) { + client.on('group_membership_request', (notification) => { + triggerWebhook(sessionWebhook, sessionId, 'group_membership_request', { notification }) + triggerWebSocket(sessionId, 'group_membership_request', { notification }) }) + } - checkIfEventisEnabled('group_update') - .then(_ => { - client.on('group_update', (notification) => { - triggerWebhook(sessionWebhook, sessionId, 'group_update', { notification }) - triggerWebSocket(sessionId, 'group_update', { notification }) - }) + if (isEventEnabled('group_update')) { + client.on('group_update', (notification) => { + triggerWebhook(sessionWebhook, sessionId, 'group_update', { notification }) + triggerWebSocket(sessionId, 'group_update', { notification }) }) + } - checkIfEventisEnabled('loading_screen') - .then(_ => { - client.on('loading_screen', (percent, message) => { - triggerWebhook(sessionWebhook, sessionId, 'loading_screen', { percent, message }) - triggerWebSocket(sessionId, 'loading_screen', { percent, message }) - }) + if (isEventEnabled('loading_screen')) { + client.on('loading_screen', (percent, message) => { + triggerWebhook(sessionWebhook, sessionId, 'loading_screen', { percent, message }) + triggerWebSocket(sessionId, 'loading_screen', { percent, message }) }) + } - checkIfEventisEnabled('media_uploaded') - .then(_ => { - client.on('media_uploaded', (message) => { - triggerWebhook(sessionWebhook, sessionId, 'media_uploaded', { message }) - triggerWebSocket(sessionId, 'media_uploaded', { message }) - }) + if (isEventEnabled('media_uploaded')) { + client.on('media_uploaded', (message) => { + triggerWebhook(sessionWebhook, sessionId, 'media_uploaded', { message }) + triggerWebSocket(sessionId, 'media_uploaded', { message }) }) + } - checkIfEventisEnabled('message') - .then(_ => { - client.on('message', async (message) => { - triggerWebhook(sessionWebhook, sessionId, 'message', { message }) - triggerWebSocket(sessionId, 'message', { message }) - if (message.hasMedia && message._data?.size < maxAttachmentSize) { - // custom service event - checkIfEventisEnabled('media').then(_ => { - message.downloadMedia().then(messageMedia => { - triggerWebhook(sessionWebhook, sessionId, 'media', { messageMedia, message }) - triggerWebSocket(sessionId, 'media', { messageMedia, message }) - }).catch(error => { - logger.error({ sessionId, err: error }, 'Failed to download media') - }) + client.on('message', async (message) => { + if (isEventEnabled('message')) { + triggerWebhook(sessionWebhook, sessionId, 'message', { message }) + triggerWebSocket(sessionId, 'message', { message }) + if (message.hasMedia && message._data?.size < maxAttachmentSize) { + // custom service event + if (isEventEnabled('media')) { + message.downloadMedia().then(messageMedia => { + triggerWebhook(sessionWebhook, sessionId, 'media', { messageMedia, message }) + triggerWebSocket(sessionId, 'media', { messageMedia, message }) + }).catch(error => { + logger.error({ sessionId, err: error }, 'Failed to download media') }) } - if (setMessagesAsSeen) { - sendMessageSeenStatus(message) - } - }) - }) + } + } + if (setMessagesAsSeen) { + // small delay to ensure the message is processed before sending seen status + await sleep(1000) + sendMessageSeenStatus(message) + } + }) - checkIfEventisEnabled('message_ack') - .then(_ => { - client.on('message_ack', async (message, ack) => { - triggerWebhook(sessionWebhook, sessionId, 'message_ack', { message, ack }) - triggerWebSocket(sessionId, 'message_ack', { message, ack }) - if (setMessagesAsSeen) { - sendMessageSeenStatus(message) - } - }) + if (isEventEnabled('message_ack')) { + client.on('message_ack', (message, ack) => { + triggerWebhook(sessionWebhook, sessionId, 'message_ack', { message, ack }) + triggerWebSocket(sessionId, 'message_ack', { message, ack }) }) + } - checkIfEventisEnabled('message_create') - .then(_ => { - client.on('message_create', async (message) => { - triggerWebhook(sessionWebhook, sessionId, 'message_create', { message }) - triggerWebSocket(sessionId, 'message_create', { message }) - if (setMessagesAsSeen) { - sendMessageSeenStatus(message) - } - }) + if (isEventEnabled('message_create')) { + client.on('message_create', (message) => { + triggerWebhook(sessionWebhook, sessionId, 'message_create', { message }) + triggerWebSocket(sessionId, 'message_create', { message }) }) + } - checkIfEventisEnabled('message_reaction') - .then(_ => { - client.on('message_reaction', (reaction) => { - triggerWebhook(sessionWebhook, sessionId, 'message_reaction', { reaction }) - triggerWebSocket(sessionId, 'message_reaction', { reaction }) - }) + if (isEventEnabled('message_reaction')) { + client.on('message_reaction', (reaction) => { + triggerWebhook(sessionWebhook, sessionId, 'message_reaction', { reaction }) + triggerWebSocket(sessionId, 'message_reaction', { reaction }) }) + } - checkIfEventisEnabled('message_edit') - .then(_ => { - client.on('message_edit', (message, newBody, prevBody) => { - triggerWebhook(sessionWebhook, sessionId, 'message_edit', { message, newBody, prevBody }) - triggerWebSocket(sessionId, 'message_edit', { message, newBody, prevBody }) - }) + if (isEventEnabled('message_edit')) { + client.on('message_edit', (message, newBody, prevBody) => { + triggerWebhook(sessionWebhook, sessionId, 'message_edit', { message, newBody, prevBody }) + triggerWebSocket(sessionId, 'message_edit', { message, newBody, prevBody }) }) + } - checkIfEventisEnabled('message_ciphertext') - .then(_ => { - client.on('message_ciphertext', (message) => { - triggerWebhook(sessionWebhook, sessionId, 'message_ciphertext', { message }) - triggerWebSocket(sessionId, 'message_ciphertext', { message }) - }) + if (isEventEnabled('message_ciphertext')) { + client.on('message_ciphertext', (message) => { + triggerWebhook(sessionWebhook, sessionId, 'message_ciphertext', { message }) + triggerWebSocket(sessionId, 'message_ciphertext', { message }) }) + } - checkIfEventisEnabled('message_revoke_everyone') - .then(_ => { - client.on('message_revoke_everyone', async (message) => { - triggerWebhook(sessionWebhook, sessionId, 'message_revoke_everyone', { message }) - triggerWebSocket(sessionId, 'message_revoke_everyone', { message }) - }) + if (isEventEnabled('message_revoke_everyone')) { + client.on('message_revoke_everyone', (message) => { + triggerWebhook(sessionWebhook, sessionId, 'message_revoke_everyone', { message }) + triggerWebSocket(sessionId, 'message_revoke_everyone', { message }) }) + } - checkIfEventisEnabled('message_revoke_me') - .then(_ => { - client.on('message_revoke_me', async (message, revokedMsg) => { - triggerWebhook(sessionWebhook, sessionId, 'message_revoke_me', { message, revokedMsg }) - triggerWebSocket(sessionId, 'message_revoke_me', { message, revokedMsg }) - }) + if (isEventEnabled('message_revoke_me')) { + client.on('message_revoke_me', (message, revokedMsg) => { + triggerWebhook(sessionWebhook, sessionId, 'message_revoke_me', { message, revokedMsg }) + triggerWebSocket(sessionId, 'message_revoke_me', { message, revokedMsg }) }) + } client.on('qr', (qr) => { // by default QR code is being updated every 20 seconds @@ -373,60 +388,53 @@ const initializeEvents = (client, sessionId) => { client.qr = null } }, 30000) - checkIfEventisEnabled('qr') - .then(_ => { - triggerWebhook(sessionWebhook, sessionId, 'qr', { qr }) - triggerWebSocket(sessionId, 'qr', { qr }) - }) + if (isEventEnabled('qr')) { + triggerWebhook(sessionWebhook, sessionId, 'qr', { qr }) + triggerWebSocket(sessionId, 'qr', { qr }) + } }) - checkIfEventisEnabled('ready') - .then(_ => { - client.on('ready', () => { - triggerWebhook(sessionWebhook, sessionId, 'ready') - triggerWebSocket(sessionId, 'ready') - }) + if (isEventEnabled('ready')) { + client.on('ready', () => { + triggerWebhook(sessionWebhook, sessionId, 'ready') + triggerWebSocket(sessionId, 'ready') }) + } - checkIfEventisEnabled('contact_changed') - .then(_ => { - client.on('contact_changed', async (message, oldId, newId, isContact) => { - triggerWebhook(sessionWebhook, sessionId, 'contact_changed', { message, oldId, newId, isContact }) - triggerWebSocket(sessionId, 'contact_changed', { message, oldId, newId, isContact }) - }) + if (isEventEnabled('contact_changed')) { + client.on('contact_changed', (message, oldId, newId, isContact) => { + triggerWebhook(sessionWebhook, sessionId, 'contact_changed', { message, oldId, newId, isContact }) + triggerWebSocket(sessionId, 'contact_changed', { message, oldId, newId, isContact }) }) + } - checkIfEventisEnabled('chat_removed') - .then(_ => { - client.on('chat_removed', async (chat) => { - triggerWebhook(sessionWebhook, sessionId, 'chat_removed', { chat }) - triggerWebSocket(sessionId, 'chat_removed', { chat }) - }) + if (isEventEnabled('chat_removed')) { + client.on('chat_removed', (chat) => { + triggerWebhook(sessionWebhook, sessionId, 'chat_removed', { chat }) + triggerWebSocket(sessionId, 'chat_removed', { chat }) }) + } - checkIfEventisEnabled('chat_archived') - .then(_ => { - client.on('chat_archived', async (chat, currState, prevState) => { - triggerWebhook(sessionWebhook, sessionId, 'chat_archived', { chat, currState, prevState }) - triggerWebSocket(sessionId, 'chat_archived', { chat, currState, prevState }) - }) + if (isEventEnabled('chat_archived')) { + client.on('chat_archived', (chat, currState, prevState) => { + triggerWebhook(sessionWebhook, sessionId, 'chat_archived', { chat, currState, prevState }) + triggerWebSocket(sessionId, 'chat_archived', { chat, currState, prevState }) }) + } - checkIfEventisEnabled('unread_count') - .then(_ => { - client.on('unread_count', async (chat) => { - triggerWebhook(sessionWebhook, sessionId, 'unread_count', { chat }) - triggerWebSocket(sessionId, 'unread_count', { chat }) - }) + if (isEventEnabled('unread_count')) { + client.on('unread_count', (chat) => { + triggerWebhook(sessionWebhook, sessionId, 'unread_count', { chat }) + triggerWebSocket(sessionId, 'unread_count', { chat }) }) + } - checkIfEventisEnabled('vote_update') - .then(_ => { - client.on('vote_update', async (vote) => { - triggerWebhook(sessionWebhook, sessionId, 'vote_update', { vote }) - triggerWebSocket(sessionId, 'vote_update', { vote }) - }) + if (isEventEnabled('vote_update')) { + client.on('vote_update', (vote) => { + triggerWebhook(sessionWebhook, sessionId, 'vote_update', { vote }) + triggerWebSocket(sessionId, 'vote_update', { vote }) }) + } } // Function to delete client session folder diff --git a/src/utils.js b/src/utils.js index 85b0504..38b2b05 100644 --- a/src/utils.js +++ b/src/utils.js @@ -38,8 +38,8 @@ const waitForNestedObject = (rootObj, nestedPath, maxWaitTime = 10000, interval }) } -const checkIfEventisEnabled = (event) => { - return new Promise((resolve) => { if (!disabledCallbacks.includes(event)) { resolve() } }) +const isEventEnabled = (event) => { + return !disabledCallbacks.includes(event) } 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 = { triggerWebhook, sendErrorResponse, waitForNestedObject, - checkIfEventisEnabled, + isEventEnabled, sendMessageSeenStatus, - decodeBase64 + decodeBase64, + sleep }