@open-wa/wa-automate 4.25.1 → 4.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- [{"env":"WA_SESSION_DATA","p":"session-data","description":"The base64 encoded sessionData used to restore a session.","type":"string","key":"sessionData"},{"env":"WA_BROWSER_WS_ENDPOINT","p":"browser-ws-endpoint","type":"string","description":"ALPHA EXPERIMENTAL FEATURE! DO NOT USE IN PRODUCTION, REQUIRES TESTING.\n\nLearn more:\n\nhttps://pptr.dev/#?product=Puppeteer&version=v3.1.0&show=api-puppeteerconnectoptions\n\nhttps://medium.com/@jaredpotter1/connecting-puppeteer-to-existing-chrome-window-8a10828149e0","key":"browserWSEndpoint"},{"env":"WA_SESSION_DATA_PATH","p":"session-data-path","type":"string","description":"The path relative to the current working directory (i.e where you run the command to start your process). This will be used to store and read your `.data.json` files. defualt to ''","key":"sessionDataPath"},{"env":"WA_SKIP_UPDATE_CHECK","p":"skip-update-check","type":"boolean","description":"If set to true, `skipUpdateCheck` will bypass the latest version check. This saves some time on boot (around 150 ms).","key":"skipUpdateCheck"},{"env":"WA_SESSION_ID","p":"session-id","type":"string","description":"This is the name of the session. You have to make sure that this is unique for every session.","key":"sessionId"},{"env":"WA_LICENSE_KEY","p":"license-key","description":"The license key to use with the session.","type":"string","key":"licenseKey"},{"env":"WA_CUSTOM_USER_AGENT","p":"custom-user-agent","type":"string","description":"You may set a custom user agent. However, due to recent developments, this is not really neccessary any more.","key":"customUserAgent"},{"env":"WA_BLOCK_CRASH_LOGS","p":"block-crash-logs","type":"boolean","description":"Setting this to true will block any network calls to crash log servers. This should keep anything you do under the radar.","key":"blockCrashLogs"},{"env":"WA_CACHE_ENABLED","p":"cache-enabled","type":"boolean","description":"Setting this to false turn off the cache. This may improve memory usage.","key":"cacheEnabled"},{"env":"WA_BROWSER_REVISION","p":"browser-revision","type":"string","description":"This is the specific browser revision to be downlaoded and used. You can find browser revision strings here: http://omahaproxy.appspot.com/ Learn more about it here: https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-browserfetcher If you're having trouble with sending images, try '737027'. If you go too far back things will start breaking !!!!!! NOTE: THIS WILL OVERRIDE useChrome and executablePath. ONLY USE THIS IF YOU KNOW WHAT YOU ARE DOING.","key":"browserRevision"},{"env":"WA_HEADLESS","p":"headless","type":"boolean","description":"By default, all instances of @open-wa/wa-automate are headless (i.e you don't see a chrome window open), you can set this to false to show the chrome/chromium window.","key":"headless"},{"env":"WA_QR_TIMEOUT","p":"qr-timeout","type":"number","description":"This determines how long the process should wait for a QR code to be scanned before killing the process entirely. To have the system wait continuously, set this to `0`.","default":60,"key":"qrTimeout"},{"env":"WA_USE_CHROME","p":"use-chrome","type":"boolean","description":"If true, the program will automatically try to detect the instance of chorme on the machine. Please note this DOES NOT override executablePath.","key":"useChrome"},{"env":"WA_QR_LOG_SKIP","p":"qr-log-skip","type":"boolean","description":"If true, skips logging the QR Code to the console.","key":"qrLogSkip"},{"env":"WA_DISABLE_SPINS","p":"disable-spins","type":"boolean","description":"Setting this to true will simplify logs for use within docker containers by disabling spins (will still print raw messages).","key":"disableSpins"},{"env":"WA_LOG_CONSOLE","p":"log-console","type":"boolean","description":"If true, this will log any console messages from the browser.","key":"logConsole"},{"env":"WA_LOG_CONSOLE_ERRORS","p":"log-console-errors","type":"boolean","description":"If true, this will log any error messages from the browser instance","key":"logConsoleErrors"},{"env":"WA_AUTH_TIMEOUT","p":"auth-timeout","type":"number","description":"This determines how long the process should wait for the session authentication. If exceeded, checks if phone is out of reach (turned of or without internet connection) and throws an error. It does not relate to the amount of time spent waiting for a qr code scan (see [[qrTimeout]]). To have the system wait continuously, set this to `0`.","key":"authTimeout"},{"env":"WA_SAFE_MODE","p":"safe-mode","type":"boolean","description":"If true, client will check if the page is valid before each command. If page is not valid, it will throw an error.","key":"safeMode"},{"env":"WA_SKIP_SESSION_SAVE","p":"skip-session-save","type":"boolean","description":"If true, the process will not save a data.json file. This means that sessions will not be saved and you will need to pass sessionData as a config param or create the session data.json file yourself","key":"skipSessionSave"},{"env":"WA_POPUP","p":"popup","type":["boolean","number"],"description":"If true, the process will open a browser window where you will see basic event logs and QR codes to authenticate the session. Usually it will open on port 3000. It can also be set to a preferred port.\n\nYou can also get the QR code png at (if localhost and port 3000):\n\n`http://localhost:3000/qr`\n\nor if you have multiple session:\n\n `http://localhost:3000/qr?sessionId=[sessionId]`","key":"popup"},{"env":"WA_QR_POP_UP_ONLY","p":"qr-pop-up-only","type":"boolean","description":"This needs to be used in conjuction with `popup`, if `popup` is not true or a number (representing a desired port) then this will not work.\n\nSetting this to true will make sure that only the qr code png is served via the web server. This is useful if you do not need the whole status page.\n\nAs mentioned in [popup](#popup), the url for the qr code is `http://localhost:3000/qr` if the port is 3000.","key":"qrPopUpOnly"},{"env":"WA_BLOCK_ASSETS","p":"block-assets","type":"boolean","description":"Setting this to true will block all assets from loading onto the page. This may result in some load time improvements but also increases instability.","key":"blockAssets"},{"env":"WA_KEEP_UPDATED","p":"keep-updated","type":"boolean","description":"[ALPHA FEATURE - ONLY IMPLEMENTED FOR TESTING - DO NOT USE IN PRODUCTION YET] Setting this to true will result in the library making sure it is always starting with the latest version of itself. This overrides `skipUpdateCheck`.","key":"keepUpdated"},{"env":"WA_RESIZABLE","p":"resizable","type":"boolean","description":"Syncs the viewport size with the window size which is how normal browsers act. Only relevant when `headless: false` and this overrides `viewport` config.","key":"resizable"},{"env":"WA_VIEWPORT","p":"viewport","type":"object","properties":{"width":{"type":"number","description":"Page width in pixels"},"height":{"type":"number","description":"Page height in pixels"}},"additionalProperties":false,"description":"Set the desired viewport height and width. For CLI, use [width]x[height] format. E.g `--viewport 1920x1080`.","key":"viewport"},{"env":"WA_LEGACY","p":"legacy","type":"boolean","description":"As the library is constantly evolving, some parts will be replaced with more efficient and improved code. In some of the infinite edge cases these new changes may not work for you. Set this to true to roll back on 'late beta' features. The reason why legacy is false by default is that in order for features to be tested they have to be released and used by everyone to find the edge cases and fix them.","key":"legacy"},{"env":"WA_DELETE_SESSION_DATA_ON_LOGOUT","p":"delete-session-data-on-logout","type":"boolean","description":"Deletes the session data file (if found) on logout event. This results in a quicker login when you restart the process.","key":"deleteSessionDataOnLogout"},{"env":"WA_KILL_PROCESS_ON_TIMEOUT","p":"kill-process-on-timeout","type":"boolean","description":"If set to true, the system will kill the whole node process when either an [[authTimeout]] or a [[qrTimeout]] has been reached. This is useful to prevent hanging processes.","key":"killProcessOnTimeout"},{"env":"WA_CORS_FIX","p":"cors-fix","type":"boolean","description":"Setting this to true will bypass web security. DO NOT DO THIS IF YOU DO NOT HAVE TO. CORS issue may arise when using a proxy.","key":"corsFix"},{"env":"WA_CALL_TIMEOUT","p":"call-timeout","type":"number","description":"Amount of time (in ms) to wait for a client method (specifically methods that interact with the WA web session) to resolve. If a client method results takes longer than the timout value then it will result in a [[PageEvaluationTimeout]] error.\n\nIf you get this error, it does not automatically mean that the method failed - it just stops your program from waiting for a client method to resolve.\n\nThis is useful if you do not rely on the results of a client method (e.g the message ID).\n\nIf set to `0`, the process will wait indefinitely for a client method to resolve.","default":0,"key":"callTimeout"},{"env":"WA_SCREENSHOT_ON_INITIALIZATION_BROWSER_ERROR","p":"screenshot-on-initialization-browser-error","type":"boolean","description":"When true, this option will take a screenshot of the browser when an unexpected error occurs within the browser during `create` initialization. The path will be `[working directory]/logs/[session ID]/[start timestamp]/[timestamp].jpg`","key":"screenshotOnInitializationBrowserError"},{"env":"WA_EVENT_MODE","p":"event-mode","type":"boolean","description":"Setting listeners may not be your cup of tea. With eventMode, all [[SimpleListener]] events will be registered automatically and be filed via the built in Events Listener.\n\nThis is useful because you can register/deregister the event listener as needed whereas the legacy method of setting callbacks are only be set once","key":"eventMode"},{"env":"WA_LOG_FILE","p":"log-file","type":"boolean","description":"If true, the system will automatically create a log of all processes relating to actions sent to the web session.\n\nThe location of the file will be relative to the process directory (pd)\n\n`[pd]/[sessionId]/[start timestamp].log`","default":false,"key":"logFile"},{"env":"WA_ID_CORRECTION","p":"id-correction","type":"boolean","description":"When true, the system will attempt to correct chatIds and groupChatIds. This means you can ignore `@c.us` and `@g.us` distinctions in some parameters.","default":false,"key":"idCorrection"},{"env":"WA_STICKER_SERVER_ENDPOINT","p":"sticker-server-endpoint","type":["string","boolean"],"description":"Redundant until self-hostable sticker server is available.","key":"stickerServerEndpoint"},{"env":"WA_GH_PATCH","p":"gh-patch","type":"boolean","description":"This will force the library to use the default cached raw github link for patches to shave a few hundred milliseconds from your launch time. If you use this option, you will need to wait about 5 minutes before trying out new patches.","key":"ghPatch"},{"env":"WA_CACHED_PATCH","p":"cached-patch","type":"boolean","description":"Setting this to `true` will save a local copy of the patches.json file (as patches.ignore.data.json) which will be used in subsequent instantiations of the session. While the rest of the launch procedure is running, the library will fetch and save a recent version of the patches to ensure your patches don't go stale. This will be ignored if the cached patches are more than a day old.","key":"cachedPatch"},{"env":"WA_LOG_DEBUG_INFO_AS_OBJECT","p":"log-debug-info-as-object","type":"boolean","description":"Setting `this` to true will replace the `console.table` with a stringified logging of the debug info object instead. This would be useful to set for smaller terminal windows. If `disableSpins` is `true` then this will also be `true`.","key":"logDebugInfoAsObject"},{"env":"WA_KILL_CLIENT_ON_LOGOUT","p":"kill-client-on-logout","type":"boolean","description":"Kill the client when a logout is detected","key":"killClientOnLogout"},{"env":"WA_THROW_ON_EXPIRED_SESSION_DATA","p":"throw-on-expired-session-data","type":"boolean","description":"This will make the `create` command return `false` if the detected session data is expired.\n\nThis will mean, the process will not attempt to automatically get a new QR code.","key":"throwOnExpiredSessionData"},{"env":"WA_USE_NATIVE_PROXY","p":"use-native-proxy","type":"boolean","description":"Some sessions may experience issues with sending media when using proxies. Using the native proxy system instead of the recommended 3rd party library may fix these issues.","key":"useNativeProxy"},{"env":"WA_RASPI","p":"raspi","type":"boolean","description":"Set this to `true` to make the library work on Raspberry Pi OS.\n\nMake sure to run the following command before running the library the first time:\n\n``` > sudo apt update -y && sudo apt install chromium-browser chromium-codecs-ffmpeg -y && sudo apt upgrade ```\n\nIf you're using the CLI, you can set this value to `true` by adding the following flag to the CLI command\n\n``` > npx @open-wa/wa-automate ... --raspi ```","key":"raspi"},{"env":"WA_MULTI_DEVICE","p":"multi-device","type":"boolean","description":"Please note that multi-device is still in beta so a lot of things may not work. It is HIGHLY suggested to NOT use this in production!!!!\n\nSet this to true if you're using the multidevice beta.","key":"multiDevice"},{"env":"WA_SESSION_DATA_BUCKET_AUTH","p":"session-data-bucket-auth","type":"string","description":"Base64 encoded S3 Bucket & Authentication object for session data files. The object should be in the same format as cloudUploadOptions.","key":"sessionDataBucketAuth"},{"env":"WA_AUTO_EMOJI","p":"auto-emoji","type":"string","description":"Set the automatic emoji detection character. Set this to false to disable auto emoji. Default is `:`.","key":"autoEmoji"},{"env":"WA_MAX_CHATS","p":"max-chats","type":"number","description":"Set the maximum amount of chats to be present in a session.","key":"maxChats"},{"env":"WA_MAX_MESSAGES","p":"max-messages","type":"number","description":"Set the maximum amount of messages to be present in a session.","key":"maxMessages"},{"env":"WA_DISCORD","p":"discord","type":"string","description":"Your Discord ID to get onto the sticker leaderboard!","key":"discord"},{"env":"WA_IGNORE_NUKE","p":"ignore-nuke","type":"boolean","description":"Don't implicitly determine if the host logged out.","key":"ignoreNuke"},{"env":"WA_ENSURE_HEADFUL_INTEGRITY","p":"ensure-headful-integrity","type":"boolean","description":"Makes sure the headless session is usable even on first login. Headful sessions are ususally only usable on reauthentication.","key":"ensureHeadfulIntegrity"},{"env":"WA_WAIT_FOR_RIPE_SESSION","p":"wait-for-ripe-session","type":"boolean","description":"wait for a valid headful session. Not required in recent versions.","key":"waitForRipeSession"}]
1
+ [{"env":"WA_SESSION_DATA","p":"session-data","description":"The base64 encoded sessionData used to restore a session.","type":"string","key":"sessionData"},{"env":"WA_BROWSER_WS_ENDPOINT","p":"browser-ws-endpoint","type":"string","description":"ALPHA EXPERIMENTAL FEATURE! DO NOT USE IN PRODUCTION, REQUIRES TESTING.\n\nLearn more:\n\nhttps://pptr.dev/#?product=Puppeteer&version=v3.1.0&show=api-puppeteerconnectoptions\n\nhttps://medium.com/@jaredpotter1/connecting-puppeteer-to-existing-chrome-window-8a10828149e0","key":"browserWSEndpoint"},{"env":"WA_SESSION_DATA_PATH","p":"session-data-path","type":"string","description":"The path relative to the current working directory (i.e where you run the command to start your process). This will be used to store and read your `.data.json` files. defualt to ''","key":"sessionDataPath"},{"env":"WA_SKIP_UPDATE_CHECK","p":"skip-update-check","type":"boolean","description":"If set to true, `skipUpdateCheck` will bypass the latest version check. This saves some time on boot (around 150 ms).","key":"skipUpdateCheck"},{"env":"WA_SESSION_ID","p":"session-id","type":"string","description":"This is the name of the session. You have to make sure that this is unique for every session.","key":"sessionId"},{"env":"WA_LICENSE_KEY","p":"license-key","description":"The license key to use with the session.","type":"string","key":"licenseKey"},{"env":"WA_CUSTOM_USER_AGENT","p":"custom-user-agent","type":"string","description":"You may set a custom user agent. However, due to recent developments, this is not really neccessary any more.","key":"customUserAgent"},{"env":"WA_BLOCK_CRASH_LOGS","p":"block-crash-logs","type":"boolean","description":"Setting this to true will block any network calls to crash log servers. This should keep anything you do under the radar.","key":"blockCrashLogs"},{"env":"WA_CACHE_ENABLED","p":"cache-enabled","type":"boolean","description":"Setting this to false turn off the cache. This may improve memory usage.","key":"cacheEnabled"},{"env":"WA_BROWSER_REVISION","p":"browser-revision","type":"string","description":"This is the specific browser revision to be downlaoded and used. You can find browser revision strings here: http://omahaproxy.appspot.com/ Learn more about it here: https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-browserfetcher If you're having trouble with sending images, try '737027'. If you go too far back things will start breaking !!!!!! NOTE: THIS WILL OVERRIDE useChrome and executablePath. ONLY USE THIS IF YOU KNOW WHAT YOU ARE DOING.","key":"browserRevision"},{"env":"WA_HEADLESS","p":"headless","type":"boolean","description":"By default, all instances of @open-wa/wa-automate are headless (i.e you don't see a chrome window open), you can set this to false to show the chrome/chromium window.","key":"headless"},{"env":"WA_QR_TIMEOUT","p":"qr-timeout","type":"number","description":"This determines how long the process should wait for a QR code to be scanned before killing the process entirely. To have the system wait continuously, set this to `0`.","default":60,"key":"qrTimeout"},{"env":"WA_USE_CHROME","p":"use-chrome","type":"boolean","description":"If true, the program will automatically try to detect the instance of chorme on the machine. Please note this DOES NOT override executablePath.","key":"useChrome"},{"env":"WA_QR_LOG_SKIP","p":"qr-log-skip","type":"boolean","description":"If true, skips logging the QR Code to the console.","key":"qrLogSkip"},{"env":"WA_DISABLE_SPINS","p":"disable-spins","type":"boolean","description":"Setting this to true will simplify logs for use within docker containers by disabling spins (will still print raw messages).","key":"disableSpins"},{"env":"WA_LOG_CONSOLE","p":"log-console","type":"boolean","description":"If true, this will log any console messages from the browser.","key":"logConsole"},{"env":"WA_LOG_CONSOLE_ERRORS","p":"log-console-errors","type":"boolean","description":"If true, this will log any error messages from the browser instance","key":"logConsoleErrors"},{"env":"WA_AUTH_TIMEOUT","p":"auth-timeout","type":"number","description":"This determines how long the process should wait for the session authentication. If exceeded, checks if phone is out of reach (turned of or without internet connection) and throws an error. It does not relate to the amount of time spent waiting for a qr code scan (see [[qrTimeout]]). To have the system wait continuously, set this to `0`.","key":"authTimeout"},{"env":"WA_SAFE_MODE","p":"safe-mode","type":"boolean","description":"If true, client will check if the page is valid before each command. If page is not valid, it will throw an error.","key":"safeMode"},{"env":"WA_SKIP_SESSION_SAVE","p":"skip-session-save","type":"boolean","description":"If true, the process will not save a data.json file. This means that sessions will not be saved and you will need to pass sessionData as a config param or create the session data.json file yourself","key":"skipSessionSave"},{"env":"WA_POPUP","p":"popup","type":["boolean","number"],"description":"If true, the process will open a browser window where you will see basic event logs and QR codes to authenticate the session. Usually it will open on port 3000. It can also be set to a preferred port.\n\nYou can also get the QR code png at (if localhost and port 3000):\n\n`http://localhost:3000/qr`\n\nor if you have multiple session:\n\n `http://localhost:3000/qr?sessionId=[sessionId]`","key":"popup"},{"env":"WA_QR_POP_UP_ONLY","p":"qr-pop-up-only","type":"boolean","description":"This needs to be used in conjuction with `popup`, if `popup` is not true or a number (representing a desired port) then this will not work.\n\nSetting this to true will make sure that only the qr code png is served via the web server. This is useful if you do not need the whole status page.\n\nAs mentioned in [popup](#popup), the url for the qr code is `http://localhost:3000/qr` if the port is 3000.","key":"qrPopUpOnly"},{"env":"WA_BLOCK_ASSETS","p":"block-assets","type":"boolean","description":"Setting this to true will block all assets from loading onto the page. This may result in some load time improvements but also increases instability.","key":"blockAssets"},{"env":"WA_KEEP_UPDATED","p":"keep-updated","type":"boolean","description":"[ALPHA FEATURE - ONLY IMPLEMENTED FOR TESTING - DO NOT USE IN PRODUCTION YET] Setting this to true will result in the library making sure it is always starting with the latest version of itself. This overrides `skipUpdateCheck`.","key":"keepUpdated"},{"env":"WA_RESIZABLE","p":"resizable","type":"boolean","description":"Syncs the viewport size with the window size which is how normal browsers act. Only relevant when `headless: false` and this overrides `viewport` config.","key":"resizable"},{"env":"WA_VIEWPORT","p":"viewport","type":"object","properties":{"width":{"type":"number","description":"Page width in pixels"},"height":{"type":"number","description":"Page height in pixels"}},"additionalProperties":false,"description":"Set the desired viewport height and width. For CLI, use [width]x[height] format. E.g `--viewport 1920x1080`.","key":"viewport"},{"env":"WA_LEGACY","p":"legacy","type":"boolean","description":"As the library is constantly evolving, some parts will be replaced with more efficient and improved code. In some of the infinite edge cases these new changes may not work for you. Set this to true to roll back on 'late beta' features. The reason why legacy is false by default is that in order for features to be tested they have to be released and used by everyone to find the edge cases and fix them.","key":"legacy"},{"env":"WA_DELETE_SESSION_DATA_ON_LOGOUT","p":"delete-session-data-on-logout","type":"boolean","description":"Deletes the session data file (if found) on logout event. This results in a quicker login when you restart the process.","key":"deleteSessionDataOnLogout"},{"env":"WA_KILL_PROCESS_ON_TIMEOUT","p":"kill-process-on-timeout","type":"boolean","description":"If set to true, the system will kill the whole node process when either an [[authTimeout]] or a [[qrTimeout]] has been reached. This is useful to prevent hanging processes.","key":"killProcessOnTimeout"},{"env":"WA_CORS_FIX","p":"cors-fix","type":"boolean","description":"Setting this to true will bypass web security. DO NOT DO THIS IF YOU DO NOT HAVE TO. CORS issue may arise when using a proxy.","key":"corsFix"},{"env":"WA_CALL_TIMEOUT","p":"call-timeout","type":"number","description":"Amount of time (in ms) to wait for a client method (specifically methods that interact with the WA web session) to resolve. If a client method results takes longer than the timout value then it will result in a [[PageEvaluationTimeout]] error.\n\nIf you get this error, it does not automatically mean that the method failed - it just stops your program from waiting for a client method to resolve.\n\nThis is useful if you do not rely on the results of a client method (e.g the message ID).\n\nIf set to `0`, the process will wait indefinitely for a client method to resolve.","default":0,"key":"callTimeout"},{"env":"WA_SCREENSHOT_ON_INITIALIZATION_BROWSER_ERROR","p":"screenshot-on-initialization-browser-error","type":"boolean","description":"When true, this option will take a screenshot of the browser when an unexpected error occurs within the browser during `create` initialization. The path will be `[working directory]/logs/[session ID]/[start timestamp]/[timestamp].jpg`","key":"screenshotOnInitializationBrowserError"},{"env":"WA_EVENT_MODE","p":"event-mode","type":"boolean","description":"Setting listeners may not be your cup of tea. With eventMode, all [[SimpleListener]] events will be registered automatically and be filed via the built in Events Listener.\n\nThis is useful because you can register/deregister the event listener as needed whereas the legacy method of setting callbacks are only be set once","key":"eventMode"},{"env":"WA_LOG_FILE","p":"log-file","type":"boolean","description":"If true, the system will automatically create a log of all processes relating to actions sent to the web session.\n\nThe location of the file will be relative to the process directory (pd)\n\n`[pd]/[sessionId]/[start timestamp].log`","default":false,"key":"logFile"},{"env":"WA_ID_CORRECTION","p":"id-correction","type":"boolean","description":"When true, the system will attempt to correct chatIds and groupChatIds. This means you can ignore `@c.us` and `@g.us` distinctions in some parameters.","default":false,"key":"idCorrection"},{"env":"WA_STICKER_SERVER_ENDPOINT","p":"sticker-server-endpoint","type":["string","boolean"],"description":"Redundant until self-hostable sticker server is available.","key":"stickerServerEndpoint"},{"env":"WA_GH_PATCH","p":"gh-patch","type":"boolean","description":"This will force the library to use the default cached raw github link for patches to shave a few hundred milliseconds from your launch time. If you use this option, you will need to wait about 5 minutes before trying out new patches.","key":"ghPatch"},{"env":"WA_CACHED_PATCH","p":"cached-patch","type":"boolean","description":"Setting this to `true` will save a local copy of the patches.json file (as patches.ignore.data.json) which will be used in subsequent instantiations of the session. While the rest of the launch procedure is running, the library will fetch and save a recent version of the patches to ensure your patches don't go stale. This will be ignored if the cached patches are more than a day old.","key":"cachedPatch"},{"env":"WA_LOG_DEBUG_INFO_AS_OBJECT","p":"log-debug-info-as-object","type":"boolean","description":"Setting `this` to true will replace the `console.table` with a stringified logging of the debug info object instead. This would be useful to set for smaller terminal windows. If `disableSpins` is `true` then this will also be `true`.","key":"logDebugInfoAsObject"},{"env":"WA_KILL_CLIENT_ON_LOGOUT","p":"kill-client-on-logout","type":"boolean","description":"Kill the client when a logout is detected","key":"killClientOnLogout"},{"env":"WA_THROW_ON_EXPIRED_SESSION_DATA","p":"throw-on-expired-session-data","type":"boolean","description":"This will make the `create` command return `false` if the detected session data is expired.\n\nThis will mean, the process will not attempt to automatically get a new QR code.","key":"throwOnExpiredSessionData"},{"env":"WA_USE_NATIVE_PROXY","p":"use-native-proxy","type":"boolean","description":"Some sessions may experience issues with sending media when using proxies. Using the native proxy system instead of the recommended 3rd party library may fix these issues.","key":"useNativeProxy"},{"env":"WA_RASPI","p":"raspi","type":"boolean","description":"Set this to `true` to make the library work on Raspberry Pi OS.\n\nMake sure to run the following command before running the library the first time:\n\n``` > sudo apt update -y && sudo apt install chromium-browser chromium-codecs-ffmpeg -y && sudo apt upgrade ```\n\nIf you're using the CLI, you can set this value to `true` by adding the following flag to the CLI command\n\n``` > npx @open-wa/wa-automate ... --raspi ```","key":"raspi"},{"env":"WA_MULTI_DEVICE","p":"multi-device","type":"boolean","description":"Please note that multi-device is still in beta so a lot of things may not work. It is HIGHLY suggested to NOT use this in production!!!!\n\nSet this to true if you're using the multidevice beta.","key":"multiDevice"},{"env":"WA_SESSION_DATA_BUCKET_AUTH","p":"session-data-bucket-auth","type":"string","description":"Base64 encoded S3 Bucket & Authentication object for session data files. The object should be in the same format as cloudUploadOptions.","key":"sessionDataBucketAuth"},{"env":"WA_AUTO_EMOJI","p":"auto-emoji","type":"string","description":"Set the automatic emoji detection character. Set this to false to disable auto emoji. Default is `:`.","key":"autoEmoji"},{"env":"WA_MAX_CHATS","p":"max-chats","type":"number","description":"Set the maximum amount of chats to be present in a session.","key":"maxChats"},{"env":"WA_MAX_MESSAGES","p":"max-messages","type":"number","description":"Set the maximum amount of messages to be present in a session.","key":"maxMessages"},{"env":"WA_DISCORD","p":"discord","type":"string","description":"Your Discord ID to get onto the sticker leaderboard!","key":"discord"},{"env":"WA_IGNORE_NUKE","p":"ignore-nuke","type":"boolean","description":"Don't implicitly determine if the host logged out.","key":"ignoreNuke"},{"env":"WA_ENSURE_HEADFUL_INTEGRITY","p":"ensure-headful-integrity","type":"boolean","description":"Makes sure the headless session is usable even on first login. Headful sessions are ususally only usable on reauthentication.","key":"ensureHeadfulIntegrity"},{"env":"WA_WAIT_FOR_RIPE_SESSION","p":"wait-for-ripe-session","type":"boolean","description":"wait for a valid headful session. Not required in recent versions.","key":"waitForRipeSession"},{"env":"WA_QR_MAX","p":"qr-max","type":"number","description":"Automatically kill the process after a set amount of qr codes","key":"qrMax"}]
@@ -733,6 +733,10 @@ export interface ConfigObject {
733
733
  * wait for a valid headful session. Not required in recent versions.
734
734
  */
735
735
  waitForRipeSession?: boolean;
736
+ /**
737
+ * Automatically kill the process after a set amount of qr codes
738
+ */
739
+ qrMax?: number;
736
740
  /**@internal */
737
741
  [x: string]: any;
738
742
  }
package/dist/cli/index.js CHANGED
@@ -113,6 +113,12 @@ function start() {
113
113
  process.exit();
114
114
  }
115
115
  }));
116
+ if (cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.chatwootUrl) {
117
+ spinner.info('Setting Up Chatwoot handler');
118
+ spinner.info('Make sure to set up the Chatwoot inbox webhook to the following path on this process: /chatwoot');
119
+ yield server_1.setupChatwoot(cliConfig, client);
120
+ spinner.succeed('Chatwoot handler set up successfully');
121
+ }
116
122
  if (cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.botPressUrl) {
117
123
  spinner.info('Setting Up Botpress handler');
118
124
  server_1.setupBotPressHandler(cliConfig, client);
@@ -0,0 +1,6 @@
1
+ import { Client } from '../..';
2
+ import { cliFlags } from '../server';
3
+ import { Request, Response } from "express";
4
+ export declare type expressMiddleware = (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
5
+ export declare const chatwootMiddleware: (cliConfig: cliFlags, client: Client) => expressMiddleware;
6
+ export declare const setupChatwootOutgoingMessageHandler: (cliConfig: cliFlags, client: Client) => Promise<void>;
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.setupChatwootOutgoingMessageHandler = exports.chatwootMiddleware = void 0;
16
+ const axios_1 = __importDefault(require("axios"));
17
+ const chatwootMiddleware = (cliConfig, client) => {
18
+ return (req, res) => __awaiter(void 0, void 0, void 0, function* () {
19
+ const processMesssage = () => __awaiter(void 0, void 0, void 0, function* () {
20
+ const promises = [];
21
+ const { body } = req;
22
+ const m = body.conversation.messages[0];
23
+ const contact = (body.conversation.meta.sender.phone_number || "").replace('+', '');
24
+ if (body.message_type === "incoming" ||
25
+ body.private ||
26
+ body.event !== "message_created" ||
27
+ !m ||
28
+ !contact)
29
+ return;
30
+ const { attachments, content } = m;
31
+ const to = `${contact}@c.us`;
32
+ if ((attachments === null || attachments === void 0 ? void 0 : attachments.length) > 0) {
33
+ //has attachments
34
+ const [firstAttachment, ...restAttachments] = attachments;
35
+ const sendAttachment = (attachment, c) => __awaiter(void 0, void 0, void 0, function* () { return client.sendImage(to, attachment.data_url, attachment.data_url.substring(attachment.data_url.lastIndexOf('/') + 1), c || '', null, true); });
36
+ //send the text as the caption with the first message only
37
+ promises.push(sendAttachment(firstAttachment, content));
38
+ restAttachments.map(sendAttachment).map(promises.push);
39
+ }
40
+ else {
41
+ //no attachments
42
+ if (!content)
43
+ return;
44
+ /**
45
+ * Check if this is a location message
46
+ */
47
+ const locationMatcher = /@(\-*\d*\.*\d*\,\-*\d*\.*\d*)/g;
48
+ const [possLoc, ...restMessage] = content.split(' ');
49
+ const locArr = possLoc.match(locationMatcher);
50
+ if (locArr) {
51
+ const [lat, lng] = locArr[0].split(',');
52
+ //grab the location message
53
+ const loc = restMessage.join(' ') || '';
54
+ promises.push(client.sendLocation(to, lat, lng, loc));
55
+ }
56
+ else {
57
+ //not a location message
58
+ promises.push(client.sendText(to, content));
59
+ }
60
+ }
61
+ return yield Promise.all(promises);
62
+ });
63
+ try {
64
+ const processAndSendResult = yield processMesssage();
65
+ res.status(200).send(processAndSendResult);
66
+ }
67
+ catch (error) {
68
+ console.log("🚀 ~ file: chatwoot.ts ~ line 62 ~ return ~ error", error);
69
+ res.status(400).send(error);
70
+ }
71
+ return;
72
+ });
73
+ };
74
+ exports.chatwootMiddleware = chatwootMiddleware;
75
+ const setupChatwootOutgoingMessageHandler = (cliConfig, client) => __awaiter(void 0, void 0, void 0, function* () {
76
+ const u = cliConfig.chatwootUrl; //e.g `"localhost:3000/api/v1/accounts/3"
77
+ const api_access_token = cliConfig.chatwootApiAccessToken;
78
+ const _u = new URL(u);
79
+ const origin = _u.origin;
80
+ const port = _u.port || 80;
81
+ const [accountId, inboxId] = u.match(/\/(app|(api\/v1))\/accounts\/\d*\/inbox\/\d*/g)[0].split('/').filter(Number);
82
+ // const accountId = u.match(/accounts\/\d*/g) && u.match(/accounts\/\d*/g)[0].replace('accounts/', '')
83
+ const resolvedInbox = inboxId || u.match(/inboxes\/\d*/g) && u.match(/inboxes\/\d*/g)[0].replace('inboxes/', '');
84
+ const cwReq = (path, method, data) => {
85
+ const url = `${origin}/api/v1/accounts/${accountId}/${path}`.replace('app.bentonow.com', 'chat.bentonow.com');
86
+ console.log(url, method, data);
87
+ return axios_1.default({
88
+ method,
89
+ data,
90
+ url,
91
+ headers: {
92
+ api_access_token
93
+ }
94
+ });
95
+ };
96
+ const contactReg = {
97
+ //WID : chatwoot contact ID
98
+ "example@c.us": "1"
99
+ };
100
+ const convoReg = {
101
+ //WID : chatwoot conversation ID
102
+ "example@c.us": "1"
103
+ };
104
+ const { data: get_inbox } = yield cwReq(`inboxes/${resolvedInbox}`, 'get');
105
+ // const inboxId = `openwa_${sessionId}`
106
+ /**
107
+ * Get the inbox and test it.
108
+ */
109
+ if (!((get_inbox === null || get_inbox === void 0 ? void 0 : get_inbox.webhook_url) || "").includes("/chatwoot"))
110
+ console.log("Please set the chatwoot inbox webhook to this sessions URL with path /chatwoot");
111
+ /**
112
+ * Get Contacts and conversations
113
+ */
114
+ const searchContact = (number) => __awaiter(void 0, void 0, void 0, function* () {
115
+ try {
116
+ const n = number.replace('@c.us', '');
117
+ const { data } = yield cwReq(`contacts/search?q=${n}&sort=phone_number`, 'get');
118
+ if (data.payload.length) {
119
+ return data.payload.find(x => (x.phone_number || "").includes(n)) || false;
120
+ }
121
+ else
122
+ false;
123
+ }
124
+ catch (error) {
125
+ return;
126
+ }
127
+ });
128
+ const getContactConversation = (number) => __awaiter(void 0, void 0, void 0, function* () {
129
+ try {
130
+ const { data } = yield cwReq(`contacts/${contactReg[number]}/conversations`, 'get');
131
+ return data.payload[0];
132
+ }
133
+ catch (error) {
134
+ return;
135
+ }
136
+ });
137
+ const createConversation = (contact_id) => __awaiter(void 0, void 0, void 0, function* () {
138
+ try {
139
+ const { data } = yield cwReq(`conversations`, 'post', {
140
+ contact_id,
141
+ "inbox_id": resolvedInbox
142
+ });
143
+ return data.payload;
144
+ }
145
+ catch (error) {
146
+ return;
147
+ }
148
+ });
149
+ const createContact = (contact) => __awaiter(void 0, void 0, void 0, function* () {
150
+ try {
151
+ const { data } = yield cwReq(`contacts`, 'post', {
152
+ "identifier": contact.id,
153
+ "name": contact.formattedName || contact.id,
154
+ "phone_number": `+${contact.id.replace('@c.us', '')}`,
155
+ "avatar_url": contact.profilePicThumbObj.eurl
156
+ });
157
+ return data.payload.contact;
158
+ }
159
+ catch (error) {
160
+ return;
161
+ }
162
+ });
163
+ const sendConversationMessage = (content, contactId, message) => __awaiter(void 0, void 0, void 0, function* () {
164
+ try {
165
+ const { data } = yield cwReq(`conversations/${convoReg[contactId]}/messages`, 'post', {
166
+ content,
167
+ "message_type": 0,
168
+ "private": false
169
+ });
170
+ return data;
171
+ }
172
+ catch (error) {
173
+ return;
174
+ }
175
+ });
176
+ // const inboxId = s.match(/conversations\/\d*/g) && s.match(/conversations\/\d*/g)[0].replace('conversations/','')
177
+ /**
178
+ * Update the chatwoot contact and conversation registries
179
+ */
180
+ client.onMessage((message) => __awaiter(void 0, void 0, void 0, function* () {
181
+ if (message.from.includes('g')) {
182
+ //chatwoot integration does not support group chats
183
+ return;
184
+ }
185
+ /**
186
+ * Does the contact exist in chatwoot?
187
+ */
188
+ if (!contactReg[message.from]) {
189
+ const contact = yield searchContact(message.from);
190
+ if (contact) {
191
+ contactReg[message.from] = contact.id;
192
+ }
193
+ else {
194
+ //create the contact
195
+ contactReg[message.from] = (yield createContact(message.sender)).id;
196
+ }
197
+ }
198
+ if (!convoReg[message.from]) {
199
+ const conversation = yield getContactConversation(message.from);
200
+ if (conversation) {
201
+ convoReg[message.from] = conversation.id;
202
+ }
203
+ else {
204
+ //create the conversation
205
+ convoReg[message.from] = (yield createConversation(contactReg[message.from])).id;
206
+ }
207
+ }
208
+ /**
209
+ * Does the conversation exist in
210
+ */
211
+ let text = message.body;
212
+ switch (message.type) {
213
+ case 'location':
214
+ text = `${message.lat},${message.lng}`;
215
+ break;
216
+ case 'buttons_response':
217
+ text = message.selectedButtonId;
218
+ break;
219
+ case 'document':
220
+ case 'image':
221
+ case 'audio':
222
+ case 'ptt':
223
+ case 'video':
224
+ if (message.cloudUrl)
225
+ text = `FILE:\t${message.cloudUrl}\n\nMESSAGE:\t${message.text}`;
226
+ break;
227
+ default:
228
+ text = message.body || "__UNHANDLED__";
229
+ break;
230
+ }
231
+ yield sendConversationMessage(text, message.from, message);
232
+ }));
233
+ });
234
+ exports.setupChatwootOutgoingMessageHandler = setupChatwootOutgoingMessageHandler;
@@ -16,5 +16,6 @@ export declare const getCommands: () => any;
16
16
  export declare const listListeners: () => string[];
17
17
  export declare const setupMediaMiddleware: () => void;
18
18
  export declare const setupTwilioCompatibleWebhook: (cliConfig: cliFlags, client: Client) => void;
19
+ export declare const setupChatwoot: (cliConfig: cliFlags, client: Client) => void;
19
20
  export declare const setupBotPressHandler: (cliConfig: cliFlags, client: Client) => void;
20
21
  export declare const setupSocketServer: (cliConfig: any, client: Client) => Promise<void>;
@@ -31,7 +31,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
31
31
  return (mod && mod.__esModule) ? mod : { "default": mod };
32
32
  };
33
33
  Object.defineProperty(exports, "__esModule", { value: true });
34
- exports.setupSocketServer = exports.setupBotPressHandler = exports.setupTwilioCompatibleWebhook = exports.setupMediaMiddleware = exports.listListeners = exports.getCommands = exports.setupRefocusDisengageMiddleware = exports.setupSwaggerStatsMiddleware = exports.setupApiDocs = exports.setupAuthenticationLayer = exports.enableCORSRequests = exports.setUpExpressApp = exports.server = exports.app = void 0;
34
+ exports.setupSocketServer = exports.setupBotPressHandler = exports.setupChatwoot = exports.setupTwilioCompatibleWebhook = exports.setupMediaMiddleware = exports.listListeners = exports.getCommands = exports.setupRefocusDisengageMiddleware = exports.setupSwaggerStatsMiddleware = exports.setupApiDocs = exports.setupAuthenticationLayer = exports.enableCORSRequests = exports.setUpExpressApp = exports.server = exports.app = void 0;
35
35
  //@ts-ignore
36
36
  const express_1 = __importDefault(require("express"));
37
37
  const http_1 = __importDefault(require("http"));
@@ -43,6 +43,7 @@ const parse_function_1 = __importDefault(require("parse-function"));
43
43
  const __1 = require("..");
44
44
  const qs_1 = __importDefault(require("qs"));
45
45
  const xmlbuilder2_1 = require("xmlbuilder2");
46
+ const chatwoot_1 = require("./integrations/chatwoot");
46
47
  exports.app = express_1.default();
47
48
  exports.server = http_1.default.createServer(exports.app);
48
49
  const trimChatId = (chatId) => chatId.replace("@c.us", "").replace("@g.us", "");
@@ -233,6 +234,11 @@ const setupTwilioCompatibleWebhook = (cliConfig, client) => {
233
234
  }));
234
235
  };
235
236
  exports.setupTwilioCompatibleWebhook = setupTwilioCompatibleWebhook;
237
+ const setupChatwoot = (cliConfig, client) => __awaiter(void 0, void 0, void 0, function* () {
238
+ exports.app.post('/chatwoot', chatwoot_1.chatwootMiddleware(cliConfig, client));
239
+ yield chatwoot_1.setupChatwootOutgoingMessageHandler(cliConfig, client);
240
+ });
241
+ exports.setupChatwoot = setupChatwoot;
236
242
  const setupBotPressHandler = (cliConfig, client) => {
237
243
  const u = cliConfig.botPressUrl;
238
244
  const sendBotPressMessage = (text, chatId, message) => __awaiter(void 0, void 0, void 0, function* () {
@@ -3,6 +3,7 @@ import { Merge, JsonObject } from 'type-fest';
3
3
  import { ConfigObject } from '../api/model/config';
4
4
  import { Spin } from '../controllers/events';
5
5
  export declare const optionKeys: string[];
6
+ export declare const optionKeysWithDefalts: string[];
6
7
  export declare const PrimitiveConverter: {
7
8
  Number: number;
8
9
  Boolean: boolean;
package/dist/cli/setup.js CHANGED
@@ -31,7 +31,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
31
31
  return (mod && mod.__esModule) ? mod : { "default": mod };
32
32
  };
33
33
  Object.defineProperty(exports, "__esModule", { value: true });
34
- exports.cli = exports.configFile = exports.envArgs = exports.helptext = exports.meowFlags = exports.cliOptionNames = exports.PrimitiveConverter = exports.optionKeys = void 0;
34
+ exports.cli = exports.configFile = exports.envArgs = exports.helptext = exports.meowFlags = exports.cliOptionNames = exports.PrimitiveConverter = exports.optionKeysWithDefalts = exports.optionKeys = void 0;
35
35
  const tools_1 = require("./../utils/tools");
36
36
  const command_line_usage_1 = __importDefault(require("command-line-usage"));
37
37
  const meow_1 = __importDefault(require("meow"));
@@ -63,6 +63,16 @@ const optionList = [{
63
63
  type: String,
64
64
  typeLabel: '{blue {underline http://localhost:5555/incoming}}',
65
65
  description: "Send twillio payloads to this URL. EASY API will also parse and processes twillio response message payloads."
66
+ }, {
67
+ name: 'chatwoot-url',
68
+ type: String,
69
+ typeLabel: '{blue {underline http://localhost:3000/api/v1/accounts/3/inboxes/1}}',
70
+ description: "The URL of the specific Chatwoot inbox you set up for this session"
71
+ }, {
72
+ name: 'chatwoot-api-access-token',
73
+ type: String,
74
+ typeLabel: '{blue {underline mEEwUGEEML2ZThMm252rLg1M}}',
75
+ description: "The access token of the specific Chatwoot inbox you set up for this session"
66
76
  },
67
77
  {
68
78
  name: 'port',
@@ -262,6 +272,7 @@ const optionList = [{
262
272
  }
263
273
  ];
264
274
  exports.optionKeys = optionList.map(({ name }) => tools_1.camelize(name));
275
+ exports.optionKeysWithDefalts = optionList.filter(o => o.hasOwnProperty('default')).map(({ name }) => tools_1.camelize(name));
265
276
  exports.PrimitiveConverter = {
266
277
  Number: 1,
267
278
  Boolean: true,
@@ -363,7 +374,16 @@ const cli = () => {
363
374
  } }),
364
375
  booleanDefault: undefined
365
376
  });
366
- const cliConfig = Object.assign(Object.assign(Object.assign({ sessionId: "session" }, _cli.flags), (exports.configFile(_cli.flags.config) || {})), exports.envArgs());
377
+ /**
378
+ * Config order should follow airmanship rules. Least maneuverable to most maneuverable.
379
+ *
380
+ * 1. ENV VARS
381
+ * 2. Config file
382
+ * 3. CLI flags
383
+ */
384
+ const nonCliConfigs = Object.assign(Object.assign({}, exports.envArgs()), (exports.configFile(_cli.flags.config) || {}));
385
+ optionList.filter(option => option.default);
386
+ const cliConfig = Object.assign(Object.assign(Object.assign({ sessionId: "session" }, nonCliConfigs), _cli.flags), exports.optionKeysWithDefalts.reduce((p, c) => nonCliConfigs.hasOwnProperty(c) ? Object.assign(Object.assign({}, p), { [c]: nonCliConfigs[c] }) : p, {}));
367
387
  const PORT = Number(cliConfig.port || process.env.PORT || 8080);
368
388
  const spinner = new events_1.Spin(cliConfig.sessionId, 'STARTUP', cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.disableSpins);
369
389
  const createConfig = Object.assign({}, cliConfig);
@@ -48,7 +48,11 @@ const puppeteerConfig = {
48
48
  // '--no-zygote',
49
49
  // '--renderer-process-limit=1',
50
50
  // '--no-first-run'
51
- '--disable-gl-drawing-for-tests'
51
+ '--disable-gl-drawing-for-tests',
52
+ //keep awake in all situations
53
+ '--disable-background-timer-throttling',
54
+ '--disable-backgrounding-occluded-windows',
55
+ '--disable-renderer-backgrounding'
52
56
  ]
53
57
  };
54
58
  exports.puppeteerConfig = puppeteerConfig;
@@ -34,6 +34,7 @@ const rxjs_1 = require("rxjs");
34
34
  const events_1 = require("./events");
35
35
  const initializer_1 = require("./initializer");
36
36
  const tools_1 = require("../utils/tools");
37
+ const browser_1 = require("./browser");
37
38
  const timeout = ms => new Promise(resolve => setTimeout(resolve, ms, 'timeout'));
38
39
  /**
39
40
  * Validates if client is authenticated
@@ -93,6 +94,7 @@ const phoneIsOutOfReach = (waPage) => __awaiter(void 0, void 0, void 0, function
93
94
  exports.phoneIsOutOfReach = phoneIsOutOfReach;
94
95
  function smartQr(waPage, config, spinner) {
95
96
  return __awaiter(this, void 0, void 0, function* () {
97
+ let qrNum = 0;
96
98
  const evalResult = yield waPage.evaluate("window.Store && window.Store.State");
97
99
  if (evalResult === false) {
98
100
  console.log('Seems as though you have been TOS_BLOCKed, unable to refresh QR Code. Please see https://github.com/open-wa/wa-automate-nodejs#best-practice for information on how to prevent this from happeing. You will most likely not get a QR Code');
@@ -113,11 +115,16 @@ function smartQr(waPage, config, spinner) {
113
115
  const qrPng = yield waPage.evaluate(`window.getQrPng()`);
114
116
  if (qrPng) {
115
117
  qrEv.emit(qrPng);
118
+ qrNum++;
119
+ tools_1.processSend('ready');
120
+ if (config.qrMax && qrNum >= config.qrMax) {
121
+ spinner.info('QR Code limit reached, exiting');
122
+ yield browser_1.kill(waPage, null, true);
123
+ }
116
124
  }
117
125
  else {
118
126
  spinner.info("Something went wrong while retreiving new the QR code but it should not affect the session launch procedure.");
119
127
  }
120
- tools_1.processSend('QR');
121
128
  }
122
129
  catch (error) {
123
130
  //@ts-ignore
@@ -1,4 +1,4 @@
1
- import { Page } from 'puppeteer';
1
+ import { Browser, Page } from 'puppeteer';
2
2
  import { Spin } from './events';
3
3
  import { ConfigObject } from '../api/model';
4
4
  export declare function initPage(sessionId?: string, config?: ConfigObject, customUserAgent?: string, spinner?: Spin, _page?: Page, skipAuth?: boolean): Promise<Page>;
@@ -6,3 +6,7 @@ export declare const deleteSessionData: (config: ConfigObject) => boolean;
6
6
  export declare const getSessionDataFilePath: (sessionId: string, config: ConfigObject) => string | boolean;
7
7
  export declare const addScript: (page: Page, js: string) => Promise<unknown>;
8
8
  export declare function injectApi(page: Page): Promise<Page>;
9
+ /**
10
+ * @internal
11
+ */
12
+ export declare const kill: (p: Page, b?: Browser, exit?: boolean) => Promise<void>;
@@ -31,7 +31,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
31
31
  return (mod && mod.__esModule) ? mod : { "default": mod };
32
32
  };
33
33
  Object.defineProperty(exports, "__esModule", { value: true });
34
- exports.injectApi = exports.addScript = exports.getSessionDataFilePath = exports.deleteSessionData = exports.initPage = void 0;
34
+ exports.kill = exports.injectApi = exports.addScript = exports.getSessionDataFilePath = exports.deleteSessionData = exports.initPage = void 0;
35
35
  const path = __importStar(require("path"));
36
36
  const fs = __importStar(require("fs"));
37
37
  const death_1 = __importDefault(require("death"));
@@ -41,6 +41,7 @@ const events_1 = require("./events");
41
41
  const pico_s3_1 = require("pico-s3");
42
42
  // eslint-disable-next-line @typescript-eslint/no-var-requires
43
43
  const puppeteer = require('puppeteer-extra');
44
+ const tree_kill_1 = __importDefault(require("tree-kill"));
44
45
  let browser;
45
46
  function initPage(sessionId, config, customUserAgent, spinner, _page, skipAuth) {
46
47
  var _a, _b, _c, _d, _e;
@@ -360,5 +361,34 @@ function getWAPage(browser) {
360
361
  death_1.default(() => __awaiter(void 0, void 0, void 0, function* () {
361
362
  //clean up code here
362
363
  if (browser)
363
- yield browser.close();
364
+ yield exports.kill(browser);
364
365
  }));
366
+ /**
367
+ * @internal
368
+ */
369
+ const kill = (p, b, exit) => __awaiter(void 0, void 0, void 0, function* () {
370
+ const killBrowser = (browser) => __awaiter(void 0, void 0, void 0, function* () {
371
+ if (!browser)
372
+ return;
373
+ const pid = (browser === null || browser === void 0 ? void 0 : browser.process()) ? browser === null || browser === void 0 ? void 0 : browser.process().pid : null;
374
+ if (!pid)
375
+ return;
376
+ if (!(p === null || p === void 0 ? void 0 : p.isClosed()))
377
+ yield (p === null || p === void 0 ? void 0 : p.close());
378
+ if (browser)
379
+ yield (browser === null || browser === void 0 ? void 0 : browser.close().catch(() => { }));
380
+ if (pid)
381
+ tree_kill_1.default(pid, 'SIGKILL');
382
+ });
383
+ if (p) {
384
+ const browser = p === null || p === void 0 ? void 0 : p.browser();
385
+ yield killBrowser(browser);
386
+ }
387
+ else if (b) {
388
+ yield killBrowser(b);
389
+ }
390
+ if (exit)
391
+ process.exit();
392
+ return;
393
+ });
394
+ exports.kill = kill;
@@ -54,7 +54,6 @@ const auth_1 = require("./auth");
54
54
  const browser_1 = require("./browser");
55
55
  const events_1 = require("./events");
56
56
  const launch_checks_1 = require("./launch_checks");
57
- const tree_kill_1 = __importDefault(require("tree-kill"));
58
57
  const cfonts_1 = __importDefault(require("cfonts"));
59
58
  const tools_1 = require("../utils/tools");
60
59
  const crypto_1 = require("crypto");
@@ -235,7 +234,7 @@ function create(config = {}) {
235
234
  if (authenticated === 'NUKE' && !(config === null || config === void 0 ? void 0 : config.ignoreNuke)) {
236
235
  //kill the browser
237
236
  spinner.fail("Session data most likely expired due to manual host account logout. Please re-authenticate this session.");
238
- yield kill(waPage);
237
+ yield browser_1.kill(waPage);
239
238
  if (config === null || config === void 0 ? void 0 : config.deleteSessionDataOnLogout)
240
239
  browser_1.deleteSessionData(config);
241
240
  if (config === null || config === void 0 ? void 0 : config.throwOnExpiredSessionData) {
@@ -256,7 +255,7 @@ function create(config = {}) {
256
255
  const outOfReach = yield Promise.race([auth_1.phoneIsOutOfReach(waPage), exports.timeout(20 * 1000)]);
257
256
  spinner.emit(outOfReach && outOfReach !== 'timeout' ? 'appOffline' : 'authTimeout');
258
257
  spinner.fail(outOfReach && outOfReach !== 'timeout' ? 'Authentication timed out. Please open the app on the phone. Shutting down' : 'Authentication timed out. Shutting down. Consider increasing authTimeout config variable: https://open-wa.github.io/wa-automate-nodejs/interfaces/configobject.html#authtimeout');
259
- yield kill(waPage);
258
+ yield browser_1.kill(waPage);
260
259
  if (config === null || config === void 0 ? void 0 : config.killProcessOnTimeout)
261
260
  process.exit();
262
261
  throw new Error(outOfReach ? 'App Offline' : 'Auth Timeout. Consider increasing authTimeout config variable: https://open-wa.github.io/wa-automate-nodejs/interfaces/configobject.html#authtimeout');
@@ -276,13 +275,13 @@ function create(config = {}) {
276
275
  }
277
276
  const result = yield Promise.race(race);
278
277
  if (result === "MULTI_DEVICE_DETECTED" && !(config === null || config === void 0 ? void 0 : config.multiDevice)) {
279
- yield kill(waPage);
278
+ yield browser_1.kill(waPage);
280
279
  return create(Object.assign(Object.assign({}, config), { multiDevice: true }));
281
280
  }
282
281
  if (result == 'timeout') {
283
282
  spinner.emit('qrTimeout');
284
283
  spinner.fail('QR scan took too long. Session Timed Out. Shutting down. Consider increasing qrTimeout config variable: https://open-wa.github.io/wa-automate-nodejs/interfaces/configobject.html#qrtimeout');
285
- yield kill(waPage);
284
+ yield browser_1.kill(waPage);
286
285
  if (config === null || config === void 0 ? void 0 : config.killProcessOnTimeout)
287
286
  process.exit();
288
287
  throw new Error('QR Timeout');
@@ -358,7 +357,7 @@ function create(config = {}) {
358
357
  if (config === null || config === void 0 ? void 0 : config.restartOnCrash)
359
358
  waPage.on('error', (error) => __awaiter(this, void 0, void 0, function* () {
360
359
  console.error('Page Crashed! Restarting...', error);
361
- yield kill(waPage);
360
+ yield browser_1.kill(waPage);
362
361
  yield create(config).then(config.restartOnCrash);
363
362
  }));
364
363
  const pureWAPI = yield launch_checks_1.checkWAPIHash();
@@ -410,13 +409,13 @@ function create(config = {}) {
410
409
  }
411
410
  else {
412
411
  spinner.fail('The session is invalid. Retrying');
413
- yield kill(waPage);
412
+ yield browser_1.kill(waPage);
414
413
  return yield create(config);
415
414
  }
416
415
  }
417
416
  catch (error) {
418
417
  spinner.emit(error.message);
419
- yield kill(waPage);
418
+ yield browser_1.kill(waPage);
420
419
  if (error.name === "ProtocolError" && ((_c = error.message) === null || _c === void 0 ? void 0 : _c.includes("Target closed"))) {
421
420
  spinner.fail(error.message);
422
421
  process.exit();
@@ -435,22 +434,3 @@ function create(config = {}) {
435
434
  });
436
435
  }
437
436
  exports.create = create;
438
- /**
439
- * @internal
440
- */
441
- const kill = (p) => __awaiter(void 0, void 0, void 0, function* () {
442
- if (p) {
443
- const browser = yield (p === null || p === void 0 ? void 0 : p.browser());
444
- if (!browser)
445
- return;
446
- const pid = (browser === null || browser === void 0 ? void 0 : browser.process()) ? browser === null || browser === void 0 ? void 0 : browser.process().pid : null;
447
- if (!pid)
448
- return;
449
- if (!(p === null || p === void 0 ? void 0 : p.isClosed()))
450
- yield (p === null || p === void 0 ? void 0 : p.close());
451
- if (browser)
452
- yield (browser === null || browser === void 0 ? void 0 : browser.close().catch(() => { }));
453
- if (pid)
454
- tree_kill_1.default(pid, 'SIGKILL');
455
- }
456
- });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-wa/wa-automate",
3
- "version": "4.25.1",
3
+ "version": "4.27.1",
4
4
  "licenseCheckUrl": "https://openwa.dev/license-check",
5
5
  "brokenMethodReportUrl": "https://openwa.dev/report-bm",
6
6
  "patches": "https://cdn.openwa.dev/patches.json",
@@ -28,7 +28,7 @@
28
28
  "docwatch": "onchange 'src/**/*.ts' 'docs-source/**/*.md' -- typedoc",
29
29
  "build:config-for-bin": "cd build && ts-node build-config-json-for-bin.ts && cd ..",
30
30
  "postinstall": "patch-package",
31
- "install": "cross-env npm_config_yes=true npx ignore-check@latest -p '**.data.json' -p '**.node-persist**' --comment 'managed by open-wa'"
31
+ "install": "cross-env npm_config_yes=true npx ignore-check@latest -p '**.data.json' -p '**.node-persist**' -p '**_IGNORE_**' --comment 'managed by open-wa'"
32
32
  },
33
33
  "husky": {
34
34
  "hooks": {
@@ -138,11 +138,11 @@
138
138
  "pico-s3": "^1.0.1",
139
139
  "pino": "^6.11.1",
140
140
  "postman-2-swagger": "^0.5.0",
141
- "puppeteer": "10.4.0",
142
- "puppeteer-extra": "^3.1.9",
143
- "puppeteer-extra-plugin-block-resources": "^2.2.7",
141
+ "puppeteer": "^13.0.0",
142
+ "puppeteer-extra": "^3.2.3",
143
+ "puppeteer-extra-plugin-block-resources": "^2.3.0",
144
144
  "puppeteer-extra-plugin-devtools": "^2.3.3",
145
- "puppeteer-extra-plugin-stealth": "^2.4.9",
145
+ "puppeteer-extra-plugin-stealth": "^2.9.0",
146
146
  "puppeteer-page-proxy": "^1.2.8",
147
147
  "qrcode-terminal": "^0.12.0",
148
148
  "qs": "^6.10.1",