@open-wa/wa-automate 4.24.2 → 4.25.0
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.
- package/bin/config-schema.json +1 -1
- package/dist/api/Client.js +5 -5
- package/dist/api/model/config.d.ts +5 -0
- package/dist/cli/index.js +1 -5
- package/dist/controllers/auth.js +12 -8
- package/dist/controllers/initializer.d.ts +1 -36
- package/dist/controllers/initializer.js +21 -165
- package/dist/controllers/patch_manager.d.ts +37 -0
- package/dist/controllers/patch_manager.js +219 -0
- package/dist/structures/Dialog.d.ts +55 -0
- package/dist/structures/Dialog.js +21 -0
- package/dist/utils/tools.d.ts +1 -0
- package/dist/utils/tools.js +27 -10
- package/package.json +1 -1
package/bin/config-schema.json
CHANGED
@@ -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_CACHED_PATCH","p":"cached-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":"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"}]
|
package/dist/api/Client.js
CHANGED
@@ -63,7 +63,7 @@ const auth_1 = require("../controllers/auth");
|
|
63
63
|
const wa_decrypt_1 = require("@open-wa/wa-decrypt");
|
64
64
|
const path = __importStar(require("path"));
|
65
65
|
const media_1 = require("./model/media");
|
66
|
-
const
|
66
|
+
const patch_manager_1 = require("../controllers/patch_manager");
|
67
67
|
const events_2 = require("./model/events");
|
68
68
|
const MessageCollector_1 = require("../structures/MessageCollector");
|
69
69
|
const init_patch_1 = require("../controllers/init_patch");
|
@@ -350,7 +350,7 @@ class Client {
|
|
350
350
|
/**
|
351
351
|
* preload license
|
352
352
|
*/
|
353
|
-
const preloadlicense = ((_c = this._createConfig) === null || _c === void 0 ? void 0 : _c.licenseKey) ? yield
|
353
|
+
const preloadlicense = ((_c = this._createConfig) === null || _c === void 0 ? void 0 : _c.licenseKey) ? yield patch_manager_1.getLicense(this._createConfig, me, this._sessionInfo, spinner) : false;
|
354
354
|
spinner.info('Refreshing session');
|
355
355
|
const START_TIME = Date.now();
|
356
356
|
spinner.info("Opening session in new tab");
|
@@ -373,7 +373,7 @@ class Client {
|
|
373
373
|
/**
|
374
374
|
* Wait for the new page to be loaded up before closing existing page
|
375
375
|
*/
|
376
|
-
yield
|
376
|
+
yield patch_manager_1.earlyInjectionCheck(newTab);
|
377
377
|
spinner.info("Checking if fresh session is authenticated...");
|
378
378
|
if (yield auth_1.isAuthenticated(newTab)) {
|
379
379
|
/**
|
@@ -394,9 +394,9 @@ class Client {
|
|
394
394
|
/**
|
395
395
|
* patch
|
396
396
|
*/
|
397
|
-
yield
|
397
|
+
yield patch_manager_1.getAndInjectLivePatch(newTab, spinner, null, this._createConfig, this._sessionInfo);
|
398
398
|
if ((_f = this._createConfig) === null || _f === void 0 ? void 0 : _f.licenseKey)
|
399
|
-
yield
|
399
|
+
yield patch_manager_1.getAndInjectLicense(newTab, this._createConfig, me, this._sessionInfo, spinner, preloadlicense);
|
400
400
|
/**
|
401
401
|
* init patch
|
402
402
|
*/
|
@@ -552,6 +552,11 @@ export interface ConfigObject {
|
|
552
552
|
* 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.
|
553
553
|
* @default `false`
|
554
554
|
*/
|
555
|
+
ghPatch?: boolean;
|
556
|
+
/**
|
557
|
+
* 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.
|
558
|
+
* @default `false`
|
559
|
+
*/
|
555
560
|
cachedPatch?: boolean;
|
556
561
|
/**
|
557
562
|
* 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`.
|
package/dist/cli/index.js
CHANGED
@@ -23,11 +23,7 @@ const server_1 = require("./server");
|
|
23
23
|
const localtunnel_1 = __importDefault(require("localtunnel"));
|
24
24
|
let checkUrl = (s) => (typeof s === "string") && is_url_superb_1.default(s);
|
25
25
|
const ready = (config) => __awaiter(void 0, void 0, void 0, function* () {
|
26
|
-
|
27
|
-
process.send('ready');
|
28
|
-
process.send('ready');
|
29
|
-
process.send('ready');
|
30
|
-
}
|
26
|
+
index_1.processSend('ready');
|
31
27
|
if (config.readyWebhook)
|
32
28
|
yield axios_1.default({
|
33
29
|
method: 'post',
|
package/dist/controllers/auth.js
CHANGED
@@ -33,6 +33,7 @@ const qrcode = __importStar(require("qrcode-terminal"));
|
|
33
33
|
const rxjs_1 = require("rxjs");
|
34
34
|
const events_1 = require("./events");
|
35
35
|
const initializer_1 = require("./initializer");
|
36
|
+
const tools_1 = require("../utils/tools");
|
36
37
|
const timeout = ms => new Promise(resolve => setTimeout(resolve, ms, 'timeout'));
|
37
38
|
/**
|
38
39
|
* Validates if client is authenticated
|
@@ -102,18 +103,21 @@ function smartQr(waPage, config, spinner) {
|
|
102
103
|
if (isAuthed)
|
103
104
|
return true;
|
104
105
|
const grabAndEmit = (qrData) => __awaiter(this, void 0, void 0, function* () {
|
106
|
+
if (qrData) {
|
107
|
+
if (!config.qrLogSkip)
|
108
|
+
qrcode.generate(qrData, { small: true });
|
109
|
+
else
|
110
|
+
console.log(`New QR Code generated. Not printing in console because qrLogSkip is set to true`);
|
111
|
+
}
|
105
112
|
try {
|
106
|
-
const
|
107
|
-
if (
|
108
|
-
qrEv.emit(
|
109
|
-
if (!config.qrLogSkip)
|
110
|
-
qrcode.generate(qrData, { small: true });
|
111
|
-
else
|
112
|
-
console.log(`New QR Code generated. Not printing in console because qrLogSkip is set to true`);
|
113
|
+
const qrPng = yield waPage.evaluate(`window.getQrPng()`);
|
114
|
+
if (qrPng) {
|
115
|
+
qrEv.emit(qrPng);
|
113
116
|
}
|
114
117
|
else {
|
115
118
|
spinner.info("Something went wrong while retreiving new the QR code but it should not affect the session launch procedure.");
|
116
119
|
}
|
120
|
+
tools_1.processSend('QR');
|
117
121
|
}
|
118
122
|
catch (error) {
|
119
123
|
//@ts-ignore
|
@@ -122,7 +126,7 @@ function smartQr(waPage, config, spinner) {
|
|
122
126
|
}
|
123
127
|
});
|
124
128
|
const qrEv = new events_1.EvEmitter(config.sessionId || 'session', 'qr');
|
125
|
-
const _hasDefaultStateYet = yield waPage.evaluate("window.Store && window.Store.State && window.Store.State.
|
129
|
+
const _hasDefaultStateYet = yield waPage.evaluate("!!(window.Store && window.Store.State && window.Store.State.Socket)");
|
126
130
|
if (!_hasDefaultStateYet) {
|
127
131
|
//expecting issue, take a screenshot then wait a few seconds before continuing
|
128
132
|
yield timeout(2000);
|
@@ -1,8 +1,6 @@
|
|
1
1
|
import { Client } from '../api/Client';
|
2
2
|
import { ConfigObject } from '../api/model/index';
|
3
|
-
|
4
|
-
import { SessionInfo } from '../api/model/sessionInfo';
|
5
|
-
import { Page } from 'puppeteer';
|
3
|
+
export declare const pkg: any, configWithCases: any, timeout: (ms: number) => Promise<unknown>;
|
6
4
|
export declare let screenshot: any;
|
7
5
|
/**
|
8
6
|
* Used to initialize the client session.
|
@@ -22,36 +20,3 @@ export declare let screenshot: any;
|
|
22
20
|
* @param config ConfigObject] The extended custom configuration
|
23
21
|
*/
|
24
22
|
export declare function create(config?: ConfigObject): Promise<Client>;
|
25
|
-
/**
|
26
|
-
* @private
|
27
|
-
*/
|
28
|
-
export declare function getPatch(config: ConfigObject, spinner?: Spin, sessionInfo?: SessionInfo): Promise<{
|
29
|
-
data: any;
|
30
|
-
tag: string;
|
31
|
-
}>;
|
32
|
-
/**
|
33
|
-
* @private
|
34
|
-
* @param page
|
35
|
-
* @param spinner
|
36
|
-
*/
|
37
|
-
export declare function injectLivePatch(page: Page, patch: {
|
38
|
-
data: any;
|
39
|
-
tag: string;
|
40
|
-
}, spinner?: Spin): Promise<void>;
|
41
|
-
/**
|
42
|
-
* @private
|
43
|
-
*/
|
44
|
-
export declare function getAndInjectLivePatch(page: Page, spinner?: Spin, preloadedPatch?: {
|
45
|
-
data: any;
|
46
|
-
tag: string;
|
47
|
-
}, config?: ConfigObject, sessionInfo?: SessionInfo): Promise<void>;
|
48
|
-
/**
|
49
|
-
* @private
|
50
|
-
*/
|
51
|
-
export declare function getLicense(config: ConfigObject, me: {
|
52
|
-
_serialized: string;
|
53
|
-
}, debugInfo: SessionInfo, spinner?: Spin): Promise<string | false>;
|
54
|
-
export declare function earlyInjectionCheck(page: Page): Promise<(page: Page) => boolean>;
|
55
|
-
export declare function getAndInjectLicense(page: Page, config: ConfigObject, me: {
|
56
|
-
_serialized: string;
|
57
|
-
}, debugInfo: SessionInfo, spinner?: Spin, preloadedLicense?: string | false): Promise<boolean>;
|
@@ -42,12 +42,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
42
42
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
43
43
|
};
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
45
|
-
exports.
|
45
|
+
exports.create = exports.screenshot = exports.timeout = exports.configWithCases = exports.pkg = void 0;
|
46
46
|
const fs = __importStar(require("fs"));
|
47
47
|
const boxen_1 = __importDefault(require("boxen"));
|
48
48
|
const os_name_1 = __importDefault(require("os-name"));
|
49
49
|
const update_notifier_1 = __importDefault(require("update-notifier"));
|
50
|
-
const crypto = __importStar(require("crypto"));
|
51
50
|
const Client_1 = require("../api/Client");
|
52
51
|
const index_1 = require("../api/model/index");
|
53
52
|
const path = __importStar(require("path"));
|
@@ -59,13 +58,14 @@ const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
59
58
|
const cfonts_1 = __importDefault(require("cfonts"));
|
60
59
|
const tools_1 = require("../utils/tools");
|
61
60
|
const crypto_1 = require("crypto");
|
62
|
-
const init_patch_1 = require("./init_patch");
|
63
61
|
const fs_extra_1 = require("fs-extra");
|
64
62
|
const pico_s3_1 = require("pico-s3");
|
65
|
-
const
|
63
|
+
const init_patch_1 = require("./init_patch");
|
64
|
+
const patch_manager_1 = require("./patch_manager");
|
65
|
+
const timeout = (ms) => {
|
66
66
|
return new Promise(resolve => setTimeout(resolve, ms, 'timeout'));
|
67
67
|
};
|
68
|
-
|
68
|
+
exports.pkg = fs_extra_1.readJsonSync(path.join(__dirname, '../../package.json')), exports.configWithCases = fs_extra_1.readJsonSync(path.join(__dirname, '../../bin/config-schema.json')), exports.timeout = timeout;
|
69
69
|
/**
|
70
70
|
* Used to initialize the client session.
|
71
71
|
*
|
@@ -97,11 +97,11 @@ function create(config = {}) {
|
|
97
97
|
}
|
98
98
|
if (!(config === null || config === void 0 ? void 0 : config.skipUpdateCheck) || (config === null || config === void 0 ? void 0 : config.keepUpdated)) {
|
99
99
|
notifier = yield update_notifier_1.default({
|
100
|
-
pkg,
|
100
|
+
pkg: exports.pkg,
|
101
101
|
updateCheckInterval: 0
|
102
102
|
});
|
103
103
|
notifier.notify();
|
104
|
-
if ((notifier === null || notifier === void 0 ? void 0 : notifier.update) && (config === null || config === void 0 ? void 0 : config.keepUpdated) && (notifier === null || notifier === void 0 ? void 0 : notifier.update.latest) !== pkg.version) {
|
104
|
+
if ((notifier === null || notifier === void 0 ? void 0 : notifier.update) && (config === null || config === void 0 ? void 0 : config.keepUpdated) && (notifier === null || notifier === void 0 ? void 0 : notifier.update.latest) !== exports.pkg.version) {
|
105
105
|
console.log('UPDATING @OPEN-WA');
|
106
106
|
const crossSpawn = yield Promise.resolve().then(() => __importStar(require('cross-spawn')));
|
107
107
|
const result = crossSpawn.sync('npm', ['i', '@open-wa/wa-automate'], { stdio: 'inherit' });
|
@@ -121,7 +121,7 @@ function create(config = {}) {
|
|
121
121
|
}
|
122
122
|
if (config === null || config === void 0 ? void 0 : config.inDocker) {
|
123
123
|
//try to infer config variables from process.env
|
124
|
-
config = Object.assign(Object.assign({}, config), tools_1.getConfigFromProcessEnv(configWithCases));
|
124
|
+
config = Object.assign(Object.assign({}, config), tools_1.getConfigFromProcessEnv(exports.configWithCases));
|
125
125
|
config.chromiumArgs = (config === null || config === void 0 ? void 0 : config.chromiumArgs) || [];
|
126
126
|
customUserAgent = config.customUserAgent;
|
127
127
|
}
|
@@ -136,8 +136,8 @@ function create(config = {}) {
|
|
136
136
|
});
|
137
137
|
console.log((config === null || config === void 0 ? void 0 : config.disableSpins) ? boxen_1.default([
|
138
138
|
`@open-wa/wa-automate `,
|
139
|
-
`${pkg.description}`,
|
140
|
-
`Version: ${pkg.version} `,
|
139
|
+
`${exports.pkg.description}`,
|
140
|
+
`Version: ${exports.pkg.version} `,
|
141
141
|
`Check out the latest changes: https://github.com/open-wa/wa-automate-nodejs#latest-changes `,
|
142
142
|
].join('\n'), { padding: 1, borderColor: 'yellow', borderStyle: 'bold' }) : prettyFont.string);
|
143
143
|
if (config === null || config === void 0 ? void 0 : config.popup) {
|
@@ -152,7 +152,7 @@ function create(config = {}) {
|
|
152
152
|
if (typeof config === 'string')
|
153
153
|
console.error("AS OF VERSION 3+ YOU CAN NO LONGER SET THE SESSION ID AS THE FIRST PARAMETER OF CREATE. CREATE CAN ONLY TAKE A CONFIG OBJECT. IF YOU STILL HAVE CONFIGS AS A SECOND PARAMETER, THEY WILL HAVE NO EFFECT! PLEASE SEE DOCS.");
|
154
154
|
spinner.start('Starting');
|
155
|
-
spinner.succeed(`Version: ${pkg.version}`);
|
155
|
+
spinner.succeed(`Version: ${exports.pkg.version}`);
|
156
156
|
spinner.info(`Initializing WA`);
|
157
157
|
/**
|
158
158
|
* Check if the IGNORE folder exists, therefore, assume that the session is MD.
|
@@ -190,11 +190,11 @@ function create(config = {}) {
|
|
190
190
|
if (msg.type() === 'error' && !msg.text().includes('apify') && !msg.text().includes('crashlogs'))
|
191
191
|
yield exports.screenshot(waPage);
|
192
192
|
}));
|
193
|
-
const WA_AUTOMATE_VERSION = `${pkg.version}${(notifier === null || notifier === void 0 ? void 0 : notifier.update) && ((notifier === null || notifier === void 0 ? void 0 : notifier.update.latest) !== pkg.version) ? ` UPDATE AVAILABLE: ${notifier === null || notifier === void 0 ? void 0 : notifier.update.latest}` : ''}`;
|
193
|
+
const WA_AUTOMATE_VERSION = `${exports.pkg.version}${(notifier === null || notifier === void 0 ? void 0 : notifier.update) && ((notifier === null || notifier === void 0 ? void 0 : notifier.update.latest) !== exports.pkg.version) ? ` UPDATE AVAILABLE: ${notifier === null || notifier === void 0 ? void 0 : notifier.update.latest}` : ''}`;
|
194
194
|
yield waPage.waitForFunction('window.Debug!=undefined && window.Debug.VERSION!=undefined');
|
195
195
|
//@ts-ignore
|
196
196
|
const WA_VERSION = yield waPage.evaluate(() => window.Debug ? window.Debug.VERSION : 'I think you have been TOS_BLOCKed');
|
197
|
-
const canInjectEarly = yield earlyInjectionCheck(waPage);
|
197
|
+
const canInjectEarly = yield patch_manager_1.earlyInjectionCheck(waPage);
|
198
198
|
const attemptingReauth = yield waPage.evaluate(`!!(localStorage['WAToken2'] || localStorage['last-wid-md'])`);
|
199
199
|
let debugInfo = {
|
200
200
|
WA_VERSION,
|
@@ -229,7 +229,7 @@ function create(config = {}) {
|
|
229
229
|
const authRace = [];
|
230
230
|
authRace.push(auth_1.isAuthenticated(waPage).catch(() => { }));
|
231
231
|
if ((config === null || config === void 0 ? void 0 : config.authTimeout) !== 0) {
|
232
|
-
authRace.push(timeout((config.authTimeout || config.multiDevice ? 120 : 60) * 1000));
|
232
|
+
authRace.push(exports.timeout((config.authTimeout || config.multiDevice ? 120 : 60) * 1000));
|
233
233
|
}
|
234
234
|
const authenticated = yield Promise.race(authRace);
|
235
235
|
if (authenticated === 'NUKE' && !(config === null || config === void 0 ? void 0 : config.ignoreNuke)) {
|
@@ -249,11 +249,11 @@ function create(config = {}) {
|
|
249
249
|
* Attempt to preload the license
|
250
250
|
*/
|
251
251
|
const earlyWid = yield waPage.evaluate(`(localStorage["last-wid"] || '').replace(/"/g,"")`);
|
252
|
-
const licensePromise = getLicense(config, {
|
252
|
+
const licensePromise = patch_manager_1.getLicense(config, {
|
253
253
|
_serialized: earlyWid
|
254
254
|
}, debugInfo, spinner);
|
255
255
|
if (authenticated == 'timeout') {
|
256
|
-
const outOfReach = yield Promise.race([auth_1.phoneIsOutOfReach(waPage), timeout(20 * 1000)]);
|
256
|
+
const outOfReach = yield Promise.race([auth_1.phoneIsOutOfReach(waPage), exports.timeout(20 * 1000)]);
|
257
257
|
spinner.emit(outOfReach && outOfReach !== 'timeout' ? 'appOffline' : 'authTimeout');
|
258
258
|
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
259
|
yield kill(waPage);
|
@@ -272,7 +272,7 @@ function create(config = {}) {
|
|
272
272
|
let to = ((config === null || config === void 0 ? void 0 : config.qrTimeout) || 60) * 1000;
|
273
273
|
if (config === null || config === void 0 ? void 0 : config.multiDevice)
|
274
274
|
to = to * 2;
|
275
|
-
race.push(timeout(to));
|
275
|
+
race.push(exports.timeout(to));
|
276
276
|
}
|
277
277
|
const result = yield Promise.race(race);
|
278
278
|
if (result === "MULTI_DEVICE_DETECTED" && !(config === null || config === void 0 ? void 0 : config.multiDevice)) {
|
@@ -308,7 +308,7 @@ function create(config = {}) {
|
|
308
308
|
//check if page is valid after 5 seconds
|
309
309
|
spinner.start('Checking if session is valid');
|
310
310
|
if (config === null || config === void 0 ? void 0 : config.safeMode)
|
311
|
-
yield timeout(5000);
|
311
|
+
yield exports.timeout(5000);
|
312
312
|
}
|
313
313
|
//@ts-ignore
|
314
314
|
const VALID_SESSION = yield waPage.evaluate(() => window.Store && window.Store.Msg ? true : false);
|
@@ -316,7 +316,7 @@ function create(config = {}) {
|
|
316
316
|
/**
|
317
317
|
* Session is valid, attempt to preload patches
|
318
318
|
*/
|
319
|
-
const patchPromise = getPatch(config, spinner, debugInfo);
|
319
|
+
const patchPromise = patch_manager_1.getPatch(config, spinner, debugInfo);
|
320
320
|
spinner.succeed('Client is ready');
|
321
321
|
const localStorage = JSON.parse(yield waPage.evaluate(() => {
|
322
322
|
return JSON.stringify(window.localStorage);
|
@@ -373,7 +373,7 @@ function create(config = {}) {
|
|
373
373
|
}
|
374
374
|
//patch issues with wapi.js
|
375
375
|
if (!(config === null || config === void 0 ? void 0 : config.skipPatches)) {
|
376
|
-
yield getAndInjectLivePatch(waPage, spinner, yield patchPromise, config, debugInfo);
|
376
|
+
yield patch_manager_1.getAndInjectLivePatch(waPage, spinner, yield patchPromise, config, debugInfo);
|
377
377
|
debugInfo.OW_KEY = yield waPage.evaluate(`window.o()`);
|
378
378
|
}
|
379
379
|
if ((config === null || config === void 0 ? void 0 : config.skipBrokenMethodsCheck) !== true)
|
@@ -392,7 +392,7 @@ function create(config = {}) {
|
|
392
392
|
const client = new Client_1.Client(waPage, config, debugInfo);
|
393
393
|
const { me } = yield client.getMe();
|
394
394
|
if ((config === null || config === void 0 ? void 0 : config.licenseKey) || me._serialized !== earlyWid) {
|
395
|
-
yield getAndInjectLicense(waPage, config, me, debugInfo, spinner, me._serialized !== earlyWid ? false : yield licensePromise);
|
395
|
+
yield patch_manager_1.getAndInjectLicense(waPage, config, me, debugInfo, spinner, me._serialized !== earlyWid ? false : yield licensePromise);
|
396
396
|
}
|
397
397
|
spinner.info("Finalizing web session...");
|
398
398
|
yield init_patch_1.injectInitPatch(waPage);
|
@@ -454,147 +454,3 @@ const kill = (p) => __awaiter(void 0, void 0, void 0, function* () {
|
|
454
454
|
tree_kill_1.default(pid, 'SIGKILL');
|
455
455
|
}
|
456
456
|
});
|
457
|
-
/**
|
458
|
-
* @private
|
459
|
-
*/
|
460
|
-
function getPatch(config, spinner, sessionInfo) {
|
461
|
-
return __awaiter(this, void 0, void 0, function* () {
|
462
|
-
const ghUrl = `https://raw.githubusercontent.com/open-wa/wa-automate-nodejs/master/patches.json`;
|
463
|
-
const hasSpin = !!spinner;
|
464
|
-
/**
|
465
|
-
* Undo below comment when a githack alternative is found.
|
466
|
-
*/
|
467
|
-
const patchesBaseUrl = (config === null || config === void 0 ? void 0 : config.cachedPatch) ? ghUrl : pkg.patches;
|
468
|
-
const patchesUrl = patchesBaseUrl + `?wv=${sessionInfo.WA_VERSION}&wav=${sessionInfo.WA_AUTOMATE_VERSION}`;
|
469
|
-
if (!spinner)
|
470
|
-
spinner = new events_1.Spin(config.sessionId, "FETCH_PATCH", config.disableSpins, true);
|
471
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.start(`Downloading ${(config === null || config === void 0 ? void 0 : config.cachedPatch) ? 'cached ' : ''}patches from ${patchesBaseUrl}`, hasSpin ? undefined : 2);
|
472
|
-
if (!axios)
|
473
|
-
axios = yield Promise.resolve().then(() => __importStar(require('axios')));
|
474
|
-
const START = Date.now();
|
475
|
-
const { data, headers } = yield axios.get(patchesUrl).catch(() => {
|
476
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.info('Downloading patches. Retrying.');
|
477
|
-
return axios.get(`${ghUrl}?v=${Date.now()}`);
|
478
|
-
});
|
479
|
-
const END = Date.now();
|
480
|
-
if (!headers['etag']) {
|
481
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.info('Generating patch hash');
|
482
|
-
headers['etag'] = crypto.createHash('md5').update(typeof data === 'string' ? data : JSON.stringify(data)).digest("hex").slice(-5);
|
483
|
-
}
|
484
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`Downloaded patches in ${(END - START) / 1000}s`);
|
485
|
-
return {
|
486
|
-
data,
|
487
|
-
tag: `${(headers.etag || '').replace(/"/g, '').slice(-5)}`
|
488
|
-
};
|
489
|
-
});
|
490
|
-
}
|
491
|
-
exports.getPatch = getPatch;
|
492
|
-
/**
|
493
|
-
* @private
|
494
|
-
* @param page
|
495
|
-
* @param spinner
|
496
|
-
*/
|
497
|
-
function injectLivePatch(page, patch, spinner) {
|
498
|
-
return __awaiter(this, void 0, void 0, function* () {
|
499
|
-
const { data, tag } = patch;
|
500
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.info('Installing patches');
|
501
|
-
yield Promise.all(data.map(patch => page.evaluate(`${patch}`)));
|
502
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`Patches Installed: ${tag}`);
|
503
|
-
});
|
504
|
-
}
|
505
|
-
exports.injectLivePatch = injectLivePatch;
|
506
|
-
/**
|
507
|
-
* @private
|
508
|
-
*/
|
509
|
-
function getAndInjectLivePatch(page, spinner, preloadedPatch, config, sessionInfo) {
|
510
|
-
return __awaiter(this, void 0, void 0, function* () {
|
511
|
-
let patch = preloadedPatch;
|
512
|
-
if (!patch)
|
513
|
-
patch = yield getPatch(config, spinner, sessionInfo);
|
514
|
-
yield injectLivePatch(page, patch, spinner);
|
515
|
-
});
|
516
|
-
}
|
517
|
-
exports.getAndInjectLivePatch = getAndInjectLivePatch;
|
518
|
-
/**
|
519
|
-
* @private
|
520
|
-
*/
|
521
|
-
function getLicense(config, me, debugInfo, spinner) {
|
522
|
-
return __awaiter(this, void 0, void 0, function* () {
|
523
|
-
if (!(config === null || config === void 0 ? void 0 : config.licenseKey) || !(me === null || me === void 0 ? void 0 : me._serialized))
|
524
|
-
return false;
|
525
|
-
if (!axios)
|
526
|
-
axios = yield Promise.resolve().then(() => __importStar(require('axios')));
|
527
|
-
const hasSpin = !!spinner;
|
528
|
-
if (!spinner)
|
529
|
-
spinner = new events_1.Spin(config.sessionId || "session", "FETCH_LICENSE", config.disableSpins, true);
|
530
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.start(`Fetching License: ${Array.isArray(config.licenseKey) ? config.licenseKey : config.licenseKey.indexOf("-") == -1 ? config.licenseKey.slice(-4) : config.licenseKey.split("-").slice(-1)[0]}`, hasSpin ? undefined : 2);
|
531
|
-
try {
|
532
|
-
const START = Date.now();
|
533
|
-
const { data } = yield axios.post(pkg.licenseCheckUrl, Object.assign({ key: config.licenseKey, number: me._serialized }, debugInfo));
|
534
|
-
const END = Date.now();
|
535
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`Downloaded License in ${(END - START) / 1000}s`);
|
536
|
-
return data;
|
537
|
-
}
|
538
|
-
catch (error) {
|
539
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.fail(`License request failed: ${error.statusCode || error.status || error.code} ${error.message}`);
|
540
|
-
return false;
|
541
|
-
}
|
542
|
-
});
|
543
|
-
}
|
544
|
-
exports.getLicense = getLicense;
|
545
|
-
function earlyInjectionCheck(page) {
|
546
|
-
return __awaiter(this, void 0, void 0, function* () {
|
547
|
-
//@ts-ignore
|
548
|
-
return yield page.evaluate(() => { if (window.webpackChunkwhatsapp_web_client) {
|
549
|
-
window.webpackChunkbuild = window.webpackChunkwhatsapp_web_client;
|
550
|
-
}
|
551
|
-
else {
|
552
|
-
(function () { const f = Object.entries(window).filter(([, o]) => o && o.push && (o.push != [].push)); if (f[0]) {
|
553
|
-
window.webpackChunkbuild = window[f[0][0]];
|
554
|
-
} })();
|
555
|
-
} return (typeof webpackChunkbuild !== "undefined"); });
|
556
|
-
});
|
557
|
-
}
|
558
|
-
exports.earlyInjectionCheck = earlyInjectionCheck;
|
559
|
-
function getAndInjectLicense(page, config, me, debugInfo, spinner, preloadedLicense) {
|
560
|
-
return __awaiter(this, void 0, void 0, function* () {
|
561
|
-
if (!(config === null || config === void 0 ? void 0 : config.licenseKey) || !(me === null || me === void 0 ? void 0 : me._serialized))
|
562
|
-
return false;
|
563
|
-
if (!axios)
|
564
|
-
axios = yield Promise.resolve().then(() => __importStar(require('axios')));
|
565
|
-
let l_err;
|
566
|
-
let data = preloadedLicense;
|
567
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.info('Checking License');
|
568
|
-
try {
|
569
|
-
if (!data) {
|
570
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.info('Fethcing License...');
|
571
|
-
data = yield getLicense(config, me, debugInfo, spinner);
|
572
|
-
}
|
573
|
-
if (data) {
|
574
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.info('Injecting License...');
|
575
|
-
const l_success = yield page.evaluate(data => eval(data), data);
|
576
|
-
if (!l_success) {
|
577
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.info('License injection failed. Getting error..');
|
578
|
-
l_err = yield page.evaluate('window.launchError');
|
579
|
-
}
|
580
|
-
else {
|
581
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.info('License injected successfully..');
|
582
|
-
const keyType = yield page.evaluate('window.KEYTYPE || false');
|
583
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`License Valid${keyType ? `: ${keyType}` : ''}`);
|
584
|
-
return true;
|
585
|
-
}
|
586
|
-
}
|
587
|
-
else
|
588
|
-
l_err = "The key is invalid";
|
589
|
-
if (l_err) {
|
590
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.fail(`License issue${l_err ? `: ${l_err}` : ""}`);
|
591
|
-
}
|
592
|
-
return false;
|
593
|
-
}
|
594
|
-
catch (error) {
|
595
|
-
spinner === null || spinner === void 0 ? void 0 : spinner.fail(`License request failed: ${error.statusCode || error.status || error.code} ${error.message}`);
|
596
|
-
return false;
|
597
|
-
}
|
598
|
-
});
|
599
|
-
}
|
600
|
-
exports.getAndInjectLicense = getAndInjectLicense;
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { ConfigObject } from '../api/model/index';
|
2
|
+
import { Spin } from './events';
|
3
|
+
import { SessionInfo } from '../api/model/sessionInfo';
|
4
|
+
import { Page } from 'puppeteer';
|
5
|
+
/**
|
6
|
+
* @private
|
7
|
+
*/
|
8
|
+
export declare function getPatch(config: ConfigObject, spinner?: Spin, sessionInfo?: SessionInfo): Promise<{
|
9
|
+
data: any;
|
10
|
+
tag: string;
|
11
|
+
}>;
|
12
|
+
/**
|
13
|
+
* @private
|
14
|
+
* @param page
|
15
|
+
* @param spinner
|
16
|
+
*/
|
17
|
+
export declare function injectLivePatch(page: Page, patch: {
|
18
|
+
data: any;
|
19
|
+
tag: string;
|
20
|
+
}, spinner?: Spin): Promise<void>;
|
21
|
+
/**
|
22
|
+
* @private
|
23
|
+
*/
|
24
|
+
export declare function getAndInjectLivePatch(page: Page, spinner?: Spin, preloadedPatch?: {
|
25
|
+
data: any;
|
26
|
+
tag: string;
|
27
|
+
}, config?: ConfigObject, sessionInfo?: SessionInfo): Promise<void>;
|
28
|
+
/**
|
29
|
+
* @private
|
30
|
+
*/
|
31
|
+
export declare function getLicense(config: ConfigObject, me: {
|
32
|
+
_serialized: string;
|
33
|
+
}, debugInfo: SessionInfo, spinner?: Spin): Promise<string | false>;
|
34
|
+
export declare function earlyInjectionCheck(page: Page): Promise<(page: Page) => boolean>;
|
35
|
+
export declare function getAndInjectLicense(page: Page, config: ConfigObject, me: {
|
36
|
+
_serialized: string;
|
37
|
+
}, debugInfo: SessionInfo, spinner?: Spin, preloadedLicense?: string | false): Promise<boolean>;
|
@@ -0,0 +1,219 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5
|
+
}) : (function(o, m, k, k2) {
|
6
|
+
if (k2 === undefined) k2 = k;
|
7
|
+
o[k2] = m[k];
|
8
|
+
}));
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11
|
+
}) : function(o, v) {
|
12
|
+
o["default"] = v;
|
13
|
+
});
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
15
|
+
if (mod && mod.__esModule) return mod;
|
16
|
+
var result = {};
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18
|
+
__setModuleDefault(result, mod);
|
19
|
+
return result;
|
20
|
+
};
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
28
|
+
});
|
29
|
+
};
|
30
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
31
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
32
|
+
};
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
34
|
+
exports.getAndInjectLicense = exports.earlyInjectionCheck = exports.getLicense = exports.getAndInjectLivePatch = exports.injectLivePatch = exports.getPatch = void 0;
|
35
|
+
const crypto = __importStar(require("crypto"));
|
36
|
+
const events_1 = require("./events");
|
37
|
+
const initializer_1 = require("./initializer");
|
38
|
+
const axios_1 = __importDefault(require("axios"));
|
39
|
+
const fs_1 = require("fs");
|
40
|
+
const { default: PQueue } = require("p-queue");
|
41
|
+
const queue = new PQueue();
|
42
|
+
/**
|
43
|
+
* @private
|
44
|
+
*/
|
45
|
+
function getPatch(config, spinner, sessionInfo) {
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
47
|
+
var data = null;
|
48
|
+
var headers = {};
|
49
|
+
const ghUrl = `https://raw.githubusercontent.com/open-wa/wa-automate-nodejs/master/patches.json`;
|
50
|
+
const hasSpin = !!spinner;
|
51
|
+
const patchFilePath = `${process.cwd()}/patches.ignore.data.json`;
|
52
|
+
/**
|
53
|
+
* If cachedPatch is true then search for patch in current working directory.
|
54
|
+
*/
|
55
|
+
if (config === null || config === void 0 ? void 0 : config.cachedPatch) {
|
56
|
+
spinner.info('Searching for cached patch');
|
57
|
+
// open file called patches.json and read as string
|
58
|
+
if (fs_1.existsSync(patchFilePath)) {
|
59
|
+
spinner.info('Found cached patch');
|
60
|
+
const lastModifiedDate = fs_1.statSync(patchFilePath).mtimeMs;
|
61
|
+
/**
|
62
|
+
* Check if patchFilePath file is more than 1 day old
|
63
|
+
*/
|
64
|
+
if ((lastModifiedDate + 86400000) < Date.now()) {
|
65
|
+
//this patch is stale.
|
66
|
+
spinner.fail('Cached patch is stale.');
|
67
|
+
}
|
68
|
+
else {
|
69
|
+
const patch = fs_1.readFileSync(patchFilePath, 'utf8');
|
70
|
+
data = JSON.parse(patch);
|
71
|
+
spinner.info('Cached patch loaded');
|
72
|
+
}
|
73
|
+
}
|
74
|
+
else
|
75
|
+
spinner.fail('Cached patch not found');
|
76
|
+
}
|
77
|
+
const freshPatchFetchPromise = () => new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
78
|
+
const patchesBaseUrl = (config === null || config === void 0 ? void 0 : config.ghPatch) ? ghUrl : initializer_1.pkg.patches;
|
79
|
+
const patchesUrl = patchesBaseUrl + `?wv=${sessionInfo.WA_VERSION}&wav=${sessionInfo.WA_AUTOMATE_VERSION}`;
|
80
|
+
if (!spinner)
|
81
|
+
spinner = new events_1.Spin(config.sessionId, "FETCH_PATCH", config.disableSpins, true);
|
82
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.start(`Downloading ${(config === null || config === void 0 ? void 0 : config.cachedPatch) ? 'cached ' : ''}patches from ${patchesBaseUrl}`, hasSpin ? undefined : 2);
|
83
|
+
const START = Date.now();
|
84
|
+
var { data, headers } = yield axios_1.default.get(patchesUrl).catch(() => {
|
85
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('Downloading patches. Retrying.');
|
86
|
+
return axios_1.default.get(`${ghUrl}?v=${Date.now()}`);
|
87
|
+
});
|
88
|
+
const END = Date.now();
|
89
|
+
if (!headers['etag']) {
|
90
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('Generating patch hash');
|
91
|
+
headers['etag'] = crypto.createHash('md5').update(typeof data === 'string' ? data : JSON.stringify(data)).digest("hex").slice(-5);
|
92
|
+
}
|
93
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`Downloaded patches in ${(END - START) / 1000}s`);
|
94
|
+
if (config === null || config === void 0 ? void 0 : config.cachedPatch) {
|
95
|
+
//save patches.json to current working directory
|
96
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('Saving patches to current working directory');
|
97
|
+
fs_1.writeFileSync(patchFilePath, JSON.stringify(data, null, 2));
|
98
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.succeed('Saved patches to current working directory');
|
99
|
+
}
|
100
|
+
return resolve({
|
101
|
+
data,
|
102
|
+
tag: `${(headers.etag || '').replace(/"/g, '').slice(-5)}`
|
103
|
+
});
|
104
|
+
}));
|
105
|
+
if ((config === null || config === void 0 ? void 0 : config.cachedPatch) && data) {
|
106
|
+
queue.add(freshPatchFetchPromise);
|
107
|
+
return { data, tag: `CACHED-${(crypto.createHash('md5').update(typeof data === 'string' ? data : JSON.stringify(data)).digest("hex").slice(-5)).replace(/"/g, '').slice(-5)}` };
|
108
|
+
}
|
109
|
+
else
|
110
|
+
return yield freshPatchFetchPromise();
|
111
|
+
});
|
112
|
+
}
|
113
|
+
exports.getPatch = getPatch;
|
114
|
+
/**
|
115
|
+
* @private
|
116
|
+
* @param page
|
117
|
+
* @param spinner
|
118
|
+
*/
|
119
|
+
function injectLivePatch(page, patch, spinner) {
|
120
|
+
return __awaiter(this, void 0, void 0, function* () {
|
121
|
+
const { data, tag } = patch;
|
122
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('Installing patches');
|
123
|
+
yield Promise.all(data.map(patch => page.evaluate(`${patch}`)));
|
124
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`Patches Installed: ${tag}`);
|
125
|
+
});
|
126
|
+
}
|
127
|
+
exports.injectLivePatch = injectLivePatch;
|
128
|
+
/**
|
129
|
+
* @private
|
130
|
+
*/
|
131
|
+
function getAndInjectLivePatch(page, spinner, preloadedPatch, config, sessionInfo) {
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
133
|
+
let patch = preloadedPatch;
|
134
|
+
if (!patch)
|
135
|
+
patch = yield getPatch(config, spinner, sessionInfo);
|
136
|
+
yield injectLivePatch(page, patch, spinner);
|
137
|
+
});
|
138
|
+
}
|
139
|
+
exports.getAndInjectLivePatch = getAndInjectLivePatch;
|
140
|
+
/**
|
141
|
+
* @private
|
142
|
+
*/
|
143
|
+
function getLicense(config, me, debugInfo, spinner) {
|
144
|
+
return __awaiter(this, void 0, void 0, function* () {
|
145
|
+
if (!(config === null || config === void 0 ? void 0 : config.licenseKey) || !(me === null || me === void 0 ? void 0 : me._serialized))
|
146
|
+
return false;
|
147
|
+
const hasSpin = !!spinner;
|
148
|
+
if (!spinner)
|
149
|
+
spinner = new events_1.Spin(config.sessionId || "session", "FETCH_LICENSE", config.disableSpins, true);
|
150
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.start(`Fetching License: ${Array.isArray(config.licenseKey) ? config.licenseKey : config.licenseKey.indexOf("-") == -1 ? config.licenseKey.slice(-4) : config.licenseKey.split("-").slice(-1)[0]}`, hasSpin ? undefined : 2);
|
151
|
+
try {
|
152
|
+
const START = Date.now();
|
153
|
+
const { data } = yield axios_1.default.post(initializer_1.pkg.licenseCheckUrl, Object.assign({ key: config.licenseKey, number: me._serialized }, debugInfo));
|
154
|
+
const END = Date.now();
|
155
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`Downloaded License in ${(END - START) / 1000}s`);
|
156
|
+
return data;
|
157
|
+
}
|
158
|
+
catch (error) {
|
159
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.fail(`License request failed: ${error.statusCode || error.status || error.code} ${error.message}`);
|
160
|
+
return false;
|
161
|
+
}
|
162
|
+
});
|
163
|
+
}
|
164
|
+
exports.getLicense = getLicense;
|
165
|
+
function earlyInjectionCheck(page) {
|
166
|
+
return __awaiter(this, void 0, void 0, function* () {
|
167
|
+
//@ts-ignore
|
168
|
+
return yield page.evaluate(() => { if (window.webpackChunkwhatsapp_web_client) {
|
169
|
+
window.webpackChunkbuild = window.webpackChunkwhatsapp_web_client;
|
170
|
+
}
|
171
|
+
else {
|
172
|
+
(function () { const f = Object.entries(window).filter(([, o]) => o && o.push && (o.push != [].push)); if (f[0]) {
|
173
|
+
window.webpackChunkbuild = window[f[0][0]];
|
174
|
+
} })();
|
175
|
+
} return (typeof webpackChunkbuild !== "undefined"); });
|
176
|
+
});
|
177
|
+
}
|
178
|
+
exports.earlyInjectionCheck = earlyInjectionCheck;
|
179
|
+
function getAndInjectLicense(page, config, me, debugInfo, spinner, preloadedLicense) {
|
180
|
+
return __awaiter(this, void 0, void 0, function* () {
|
181
|
+
if (!(config === null || config === void 0 ? void 0 : config.licenseKey) || !(me === null || me === void 0 ? void 0 : me._serialized))
|
182
|
+
return false;
|
183
|
+
let l_err;
|
184
|
+
let data = preloadedLicense;
|
185
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('Checking License');
|
186
|
+
try {
|
187
|
+
if (!data) {
|
188
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('Fethcing License...');
|
189
|
+
data = yield getLicense(config, me, debugInfo, spinner);
|
190
|
+
}
|
191
|
+
if (data) {
|
192
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('Injecting License...');
|
193
|
+
const l_success = yield page.evaluate(data => eval(data), data);
|
194
|
+
if (!l_success) {
|
195
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('License injection failed. Getting error..');
|
196
|
+
l_err = yield page.evaluate('window.launchError');
|
197
|
+
}
|
198
|
+
else {
|
199
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.info('License injected successfully..');
|
200
|
+
const keyType = yield page.evaluate('window.KEYTYPE || false');
|
201
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.succeed(`License Valid${keyType ? `: ${keyType}` : ''}`);
|
202
|
+
return true;
|
203
|
+
}
|
204
|
+
}
|
205
|
+
else
|
206
|
+
l_err = "The key is invalid";
|
207
|
+
if (l_err) {
|
208
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.fail(`License issue${l_err ? `: ${l_err}` : ""}`);
|
209
|
+
}
|
210
|
+
return false;
|
211
|
+
}
|
212
|
+
catch (error) {
|
213
|
+
spinner === null || spinner === void 0 ? void 0 : spinner.fail(`License request failed: ${error.statusCode || error.status || error.code} ${error.message}`);
|
214
|
+
return false;
|
215
|
+
}
|
216
|
+
});
|
217
|
+
}
|
218
|
+
exports.getAndInjectLicense = getAndInjectLicense;
|
219
|
+
// export * from './init_patch';
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import { Message } from "..";
|
2
|
+
export interface CurrentDialogProps {
|
3
|
+
[k: string]: any;
|
4
|
+
}
|
5
|
+
export interface DialogState {
|
6
|
+
currentStep: number;
|
7
|
+
currentProps: any;
|
8
|
+
lastInput: any;
|
9
|
+
isComplete: boolean;
|
10
|
+
isError: boolean;
|
11
|
+
errorMessage: string;
|
12
|
+
}
|
13
|
+
export interface DialogTemplate {
|
14
|
+
"dialogId": string;
|
15
|
+
"privateOnly": boolean;
|
16
|
+
"identifier": string;
|
17
|
+
"successMessage": string;
|
18
|
+
"startMessage": string;
|
19
|
+
"properties": {
|
20
|
+
[key: string]: DialogProperty;
|
21
|
+
};
|
22
|
+
}
|
23
|
+
export declare type CheckFunction = (lastReceivedMessage: Message, currentProps: CurrentDialogProps) => boolean;
|
24
|
+
export interface DialogProperty {
|
25
|
+
"order": number;
|
26
|
+
"key": string;
|
27
|
+
"prompt": string;
|
28
|
+
"type": string;
|
29
|
+
"skipCondition"?: CheckFunction;
|
30
|
+
"options"?: DialogButtons[] | DialogListMessageSection[];
|
31
|
+
"validation": DialogValidation[];
|
32
|
+
}
|
33
|
+
export interface DialogButtons {
|
34
|
+
label: string;
|
35
|
+
value: string;
|
36
|
+
}
|
37
|
+
export interface DialogListMessageSection {
|
38
|
+
title: string;
|
39
|
+
rows: DialogListMessageRow[];
|
40
|
+
}
|
41
|
+
export interface DialogListMessageRow {
|
42
|
+
title: string;
|
43
|
+
description: string;
|
44
|
+
value: string;
|
45
|
+
}
|
46
|
+
export interface DialogValidation {
|
47
|
+
"type": ValidationType;
|
48
|
+
"value": string | CheckFunction;
|
49
|
+
"errorMessage": string;
|
50
|
+
}
|
51
|
+
export declare enum ValidationType {
|
52
|
+
REGEX = "regex",
|
53
|
+
LENGTH = "length",
|
54
|
+
CHECK = "check"
|
55
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.ValidationType = void 0;
|
4
|
+
var ValidationType;
|
5
|
+
(function (ValidationType) {
|
6
|
+
ValidationType["REGEX"] = "regex";
|
7
|
+
ValidationType["LENGTH"] = "length";
|
8
|
+
ValidationType["CHECK"] = "check";
|
9
|
+
})(ValidationType = exports.ValidationType || (exports.ValidationType = {}));
|
10
|
+
// async function processDialog(dialog: DialogTemplate, chatId: ChatId, client: Client){
|
11
|
+
// if(dialog.privateOnly && chatId.includes('g')) return;
|
12
|
+
// const requiredProperties = Object.keys(dialog.properties);
|
13
|
+
// const requiredPropertiesInOrder = requiredProperties.map(prop=>dialog.properties[prop]).sort((a, b) => a.order - b.order);
|
14
|
+
// /**
|
15
|
+
// * Send start dialog message
|
16
|
+
// */
|
17
|
+
// await client.sendText(chatId, dialog.startMessage);
|
18
|
+
// requiredPropertiesInOrder.map((diaProp: DialogProperty) => {
|
19
|
+
// diaProp.type
|
20
|
+
// })
|
21
|
+
// }
|
package/dist/utils/tools.d.ts
CHANGED
@@ -24,3 +24,4 @@ export declare const getDUrl: (url: string, optionsOverride?: AxiosRequestConfig
|
|
24
24
|
* Use this to extract the mime type from a [[DataURL]]
|
25
25
|
*/
|
26
26
|
export declare const base64MimeType: (dUrl: DataURL) => string;
|
27
|
+
export declare const processSend: (message: string) => void;
|
package/dist/utils/tools.js
CHANGED
@@ -23,7 +23,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
23
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
24
24
|
};
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
26
|
-
exports.base64MimeType = exports.getDUrl = exports.isDataURL = exports.isBase64 = exports.camelize = exports.without = exports.getConfigFromProcessEnv = exports.smartUserAgent = void 0;
|
26
|
+
exports.processSend = exports.base64MimeType = exports.getDUrl = exports.isDataURL = exports.isBase64 = exports.camelize = exports.without = exports.getConfigFromProcessEnv = exports.smartUserAgent = void 0;
|
27
27
|
const axios_1 = __importDefault(require("axios"));
|
28
28
|
/**
|
29
29
|
* Use this to generate a more likely valid user agent. It makes sure it has the WA part and replaces any windows or linux os info with mac.
|
@@ -31,10 +31,16 @@ const axios_1 = __importDefault(require("axios"));
|
|
31
31
|
* @param v The WA version from the debug info. This is optional. default is 2.2117.5
|
32
32
|
*/
|
33
33
|
const smartUserAgent = (useragent, v = '2.2117.5') => {
|
34
|
-
useragent = useragent.replace(useragent
|
34
|
+
useragent = useragent.replace(useragent
|
35
|
+
.match(/\(([^()]*)\)/g)
|
36
|
+
.find((x) => x.toLowerCase().includes('linux') ||
|
37
|
+
x.toLowerCase().includes('windows')), '(Macintosh; Intel Mac OS X 10_15_2)');
|
35
38
|
if (!useragent.includes('WhatsApp'))
|
36
39
|
return `WhatsApp/${v} ${useragent}`;
|
37
|
-
return useragent.replace(useragent
|
40
|
+
return useragent.replace(useragent
|
41
|
+
.match(/WhatsApp\/([.\d])*/g)[0]
|
42
|
+
.match(/[.\d]*/g)
|
43
|
+
.find((x) => x), v);
|
38
44
|
};
|
39
45
|
exports.smartUserAgent = smartUserAgent;
|
40
46
|
const getConfigFromProcessEnv = (json) => {
|
@@ -59,9 +65,11 @@ const without = (obj, key) => {
|
|
59
65
|
exports.without = without;
|
60
66
|
const camelize = (str) => {
|
61
67
|
const arr = str.split('-');
|
62
|
-
const capital = arr.map((item, index) => index
|
68
|
+
const capital = arr.map((item, index) => index
|
69
|
+
? item.charAt(0).toUpperCase() + item.slice(1).toLowerCase()
|
70
|
+
: item.toLowerCase());
|
63
71
|
// ^-- change here.
|
64
|
-
const capitalString = capital.join(
|
72
|
+
const capitalString = capital.join('');
|
65
73
|
return capitalString;
|
66
74
|
};
|
67
75
|
exports.camelize = camelize;
|
@@ -71,9 +79,9 @@ const isBase64 = (str) => {
|
|
71
79
|
return false;
|
72
80
|
}
|
73
81
|
const firstPaddingChar = str.indexOf('=');
|
74
|
-
return firstPaddingChar === -1 ||
|
82
|
+
return (firstPaddingChar === -1 ||
|
75
83
|
firstPaddingChar === len - 1 ||
|
76
|
-
(firstPaddingChar === len - 2 && str[len - 1] === '=');
|
84
|
+
(firstPaddingChar === len - 2 && str[len - 1] === '='));
|
77
85
|
};
|
78
86
|
exports.isBase64 = isBase64;
|
79
87
|
const isDataURL = (s) => !!s.match(/^data:((?:\w+\/(?:(?!;).)+)?)((?:;[\w\W]*?[^;])*),(.+)$/g);
|
@@ -88,9 +96,9 @@ exports.isDataURL = isDataURL;
|
|
88
96
|
const getDUrl = (url, optionsOverride = {}) => __awaiter(void 0, void 0, void 0, function* () {
|
89
97
|
// eslint-disable-next-line no-useless-catch
|
90
98
|
try {
|
91
|
-
const res = yield axios_1.default(Object.assign(Object.assign({ method:
|
92
|
-
|
93
|
-
'Upgrade-Insecure-Requests': 1
|
99
|
+
const res = yield axios_1.default(Object.assign(Object.assign({ method: 'get', url, headers: {
|
100
|
+
DNT: 1,
|
101
|
+
'Upgrade-Insecure-Requests': 1,
|
94
102
|
} }, optionsOverride), { responseType: 'arraybuffer' }));
|
95
103
|
const dUrl = `data:${res.headers['content-type']};base64,${Buffer.from(res.data, 'binary').toString('base64')}`;
|
96
104
|
return dUrl;
|
@@ -116,3 +124,12 @@ const base64MimeType = (dUrl) => {
|
|
116
124
|
return result;
|
117
125
|
};
|
118
126
|
exports.base64MimeType = base64MimeType;
|
127
|
+
const processSend = (message) => {
|
128
|
+
if (process.send) {
|
129
|
+
process.send(message);
|
130
|
+
process.send(message);
|
131
|
+
process.send(message);
|
132
|
+
}
|
133
|
+
return;
|
134
|
+
};
|
135
|
+
exports.processSend = processSend;
|
package/package.json
CHANGED