@open-wa/wa-automate 4.23.15 → 4.24.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.
@@ -355,7 +355,8 @@ class Client {
355
355
  const START_TIME = Date.now();
356
356
  spinner.info("Opening session in new tab");
357
357
  const newTab = yield this._page.browser().newPage();
358
- yield newTab.goto(puppeteer_config_1.puppeteerConfig.WAUrl);
358
+ yield browser_1.initPage(this.getSessionId(), this._createConfig, this._createConfig.customUserAgent, spinner, newTab, true);
359
+ // await newTab.goto(puppeteerConfig.WAUrl);
359
360
  //Two promises. One that closes the previous page, one that sets up the new page
360
361
  const closePageOnConflict = () => __awaiter(this, void 0, void 0, function* () {
361
362
  const useHere = yield this._page.evaluate(() => WAPI.getUseHereString());
@@ -470,20 +471,28 @@ class Client {
470
471
  const res = yield this._page.evaluate(pageFunction, ...args);
471
472
  if (this._createConfig.onError && typeof res == "string" && (res.startsWith("Error") || res.startsWith("ERROR"))) {
472
473
  const e = this._createConfig.onError;
473
- if (e == model_1.OnError.AS_STRING || e == model_1.OnError.NOTHING)
474
- return res;
475
- if (e == model_1.OnError.LOG_AND_FALSE) {
476
- console.error(res);
477
- return true;
478
- }
479
- if (e == model_1.OnError.LOG_AND_STRING) {
474
+ /**
475
+ * Log error
476
+ */
477
+ if (e == model_1.OnError.LOG_AND_FALSE ||
478
+ e == model_1.OnError.LOG_AND_STRING ||
479
+ res.includes("get.openwa.dev"))
480
480
  console.error(res);
481
+ /**
482
+ * Return res
483
+ */
484
+ if (e == model_1.OnError.AS_STRING ||
485
+ e == model_1.OnError.NOTHING ||
486
+ e == model_1.OnError.LOG_AND_STRING)
481
487
  return res;
482
- }
488
+ /**
489
+ * Return false
490
+ */
491
+ if (e == model_1.OnError.LOG_AND_FALSE ||
492
+ e == model_1.OnError.RETURN_FALSE)
493
+ return false;
483
494
  if (e == model_1.OnError.RETURN_ERROR)
484
495
  return new Error(res);
485
- if (e == model_1.OnError.RETURN_FALSE)
486
- return false;
487
496
  if (e == model_1.OnError.THROW)
488
497
  throw new Error(res);
489
498
  }
@@ -5,26 +5,83 @@ export interface Chat {
5
5
  archive: boolean;
6
6
  changeNumberNewJid: any;
7
7
  changeNumberOldJid: any;
8
+ /**
9
+ * The contact related to this chat
10
+ */
8
11
  contact: Contact;
12
+ /**
13
+ * Group metadata for this chat
14
+ */
9
15
  groupMetadata: GroupMetadata;
16
+ /**
17
+ * The id of the chat
18
+ */
10
19
  id: ChatId;
20
+ /**
21
+ * If the chat is a group chat is restricted
22
+ */
11
23
  isAnnounceGrpRestrict: any;
24
+ /**
25
+ * The title of the chat
26
+ */
12
27
  formattedTitle?: string;
28
+ /**
29
+ * Whether your host account is able to send messages to this chat
30
+ */
13
31
  canSend?: boolean;
32
+ /**
33
+ * Whether the chat is a group chat
34
+ */
14
35
  isGroup: boolean;
36
+ /**
37
+ * Whether the chat is a group chat and the group is restricted
38
+ */
15
39
  isReadOnly: boolean;
16
40
  kind: string;
41
+ /**
42
+ * The labels attached to this chat.
43
+ */
17
44
  labels: any;
45
+ /**
46
+ * The ID of the last message received in this chat
47
+ */
18
48
  lastReceivedKey: any;
19
49
  modifyTag: number;
50
+ /**
51
+ * The messages in the chat
52
+ */
20
53
  msgs: any;
54
+ /**
55
+ * The expiration timestamp of the chat mute
56
+ */
21
57
  muteExpiration: number;
58
+ /**
59
+ * The name of the chat
60
+ */
22
61
  name: string;
62
+ /**
63
+ * Whether the chat is marked as spam
64
+ */
23
65
  notSpam: boolean;
66
+ /**
67
+ * Messages that are pending to be sent
68
+ */
24
69
  pendingMsgs: boolean;
70
+ /**
71
+ * Whether the chat is pinned
72
+ */
25
73
  pin: number;
74
+ /**
75
+ * The presence state of the chat participant
76
+ */
26
77
  presence: any;
78
+ /**
79
+ * The timestamp of the last interaction in the chat
80
+ */
27
81
  t: number;
82
+ /**
83
+ * The number of undread messages in this chat
84
+ */
28
85
  unreadCount: number;
29
86
  ack?: any;
30
87
  /**
@@ -44,6 +44,14 @@ export declare type StickerMetadata = {
44
44
  * @default `attention`
45
45
  */
46
46
  cropPosition?: 'top' | 'right top' | 'right' | 'right bottom' | 'bottom' | 'left bottom' | 'left' | 'left top' | 'north' | 'northeast' | 'east' | 'southeast' | 'south' | 'southwest' | 'west' | 'northwest' | 'center' | 'centre' | 'entropy' | 'attention';
47
+ /**
48
+ * The corner radius of the sticker when `stickerMetadata.circle` is set to true.
49
+ * @default `100`
50
+ * @minimum `1`
51
+ * @maximum `100`
52
+ * @multipleOf `1`
53
+ */
54
+ cornerRadius?: number;
47
55
  };
48
56
  export declare type Mp4StickerConversionProcessOptions = {
49
57
  /**
@@ -37,7 +37,8 @@ const postman_2_swagger_1 = __importDefault(require("postman-2-swagger"));
37
37
  const fs_extra_1 = require("fs-extra");
38
38
  const typeconv_1 = require("typeconv");
39
39
  const fs = __importStar(require("fs"));
40
- const glob_promise_1 = __importDefault(require("glob-promise"));
40
+ const glob = require("tiny-glob");
41
+ const path = __importStar(require("path"));
41
42
  exports.collections = {};
42
43
  const generateCollections = (config, spinner) => __awaiter(void 0, void 0, void 0, function* () {
43
44
  let swCol = null;
@@ -118,7 +119,7 @@ const getTypeSchemas = () => __awaiter(void 0, void 0, void 0, function* () {
118
119
  const { convert } = typeconv_1.makeConverter(reader, writer, {
119
120
  simplify: true
120
121
  });
121
- const s = (yield Promise.all([...(yield glob_promise_1.default('../**/*.d.ts')), ...(yield glob_promise_1.default('../**/message.js')), ...(yield glob_promise_1.default('../**/chat.js'))])).filter(f => !f.includes('node_modules'));
122
+ const s = (yield Promise.all([...(yield glob(path.resolve(__dirname, '../**/*.d.ts'))), ...(yield glob(path.resolve(__dirname, '../**/message.js'))), ...(yield glob(path.resolve(__dirname, '../**/chat.js')))])).filter(f => !f.includes('node_modules'));
122
123
  const res = {};
123
124
  yield Promise.all(s.map((x) => __awaiter(void 0, void 0, void 0, function* () {
124
125
  var _a, _b;
package/dist/cli/index.js CHANGED
@@ -20,6 +20,7 @@ const axios_1 = __importDefault(require("axios"));
20
20
  const setup_1 = require("./setup");
21
21
  const collections_1 = require("./collections");
22
22
  const server_1 = require("./server");
23
+ const localtunnel_1 = __importDefault(require("localtunnel"));
23
24
  let checkUrl = (s) => (typeof s === "string") && is_url_superb_1.default(s);
24
25
  const ready = (config) => __awaiter(void 0, void 0, void 0, function* () {
25
26
  if (process.send) {
@@ -176,6 +177,11 @@ function start() {
176
177
  spinner.succeed(`\n• Listening on port ${PORT}!`);
177
178
  yield ready(Object.assign(Object.assign(Object.assign(Object.assign({}, cliConfig), createConfig), client.getSessionInfo()), { hostAccountNumber: yield client.getHostNumber() }));
178
179
  }));
180
+ if (cliConfig.tunnel) {
181
+ spinner.info(`\n• Setting up external tunnel`);
182
+ const tunnel = yield localtunnel_1.default({ port: PORT });
183
+ spinner.succeed(`\n\t${terminal_link_1.default('External address', tunnel.url)}`);
184
+ }
179
185
  const apiDocsUrl = cliConfig.apiHost ? `${cliConfig.apiHost}/api-docs/ ` : `${cliConfig.host.includes('http') ? '' : 'http://'}${cliConfig.host}:${PORT}/api-docs/ `;
180
186
  const link = terminal_link_1.default('API Explorer', apiDocsUrl);
181
187
  if (cliConfig && cliConfig.generateApiDocs)
package/dist/cli/setup.js CHANGED
@@ -251,6 +251,11 @@ const optionList = [{
251
251
  type: Boolean,
252
252
  description: "Don't validate webhook URLs. Enables use of non-FQDNs."
253
253
  },
254
+ {
255
+ name: 'tunnel',
256
+ type: Boolean,
257
+ description: "Expose a tunnel to your EASY API session - this is for testing and it is unsecured."
258
+ },
254
259
  {
255
260
  name: 'help',
256
261
  description: 'Print this usage guide.'
@@ -4,8 +4,8 @@ declare const puppeteerConfig: {
4
4
  height: number;
5
5
  chromiumArgs: string[];
6
6
  };
7
- export declare const useragent = "WhatsApp/2.2108.8 Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36";
8
7
  export declare const createUserAgent: (waVersion: string) => string;
8
+ export declare const useragent: string;
9
9
  export { puppeteerConfig };
10
10
  export declare const width: number;
11
11
  export declare const height: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.height = exports.width = exports.puppeteerConfig = exports.createUserAgent = exports.useragent = void 0;
3
+ exports.height = exports.width = exports.puppeteerConfig = exports.useragent = exports.createUserAgent = void 0;
4
4
  const puppeteerConfig = {
5
5
  WAUrl: 'https://web.whatsapp.com',
6
6
  width: 1440,
@@ -52,8 +52,8 @@ const puppeteerConfig = {
52
52
  ]
53
53
  };
54
54
  exports.puppeteerConfig = puppeteerConfig;
55
- exports.useragent = 'WhatsApp/2.2108.8 Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36';
56
- const createUserAgent = (waVersion) => `WhatsApp/${waVersion} Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36`;
55
+ const createUserAgent = (waVersion) => `WhatsApp/${waVersion} Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36`;
57
56
  exports.createUserAgent = createUserAgent;
57
+ exports.useragent = exports.createUserAgent('2.2144.11');
58
58
  exports.width = puppeteerConfig.width;
59
59
  exports.height = puppeteerConfig.height;
@@ -1,7 +1,7 @@
1
1
  import { Page } from 'puppeteer';
2
2
  import { Spin } from './events';
3
3
  import { ConfigObject } from '../api/model';
4
- export declare function initPage(sessionId?: string, config?: ConfigObject, customUserAgent?: string, spinner?: Spin): Promise<Page>;
4
+ export declare function initPage(sessionId?: string, config?: ConfigObject, customUserAgent?: string, spinner?: Spin, _page?: Page, skipAuth?: boolean): Promise<Page>;
5
5
  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>;
@@ -42,7 +42,7 @@ 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
44
  let browser;
45
- function initPage(sessionId, config, customUserAgent, spinner) {
45
+ function initPage(sessionId, config, customUserAgent, spinner, _page, skipAuth) {
46
46
  var _a, _b, _c, _d, _e;
47
47
  return __awaiter(this, void 0, void 0, function* () {
48
48
  const setupPromises = [];
@@ -52,10 +52,13 @@ function initPage(sessionId, config, customUserAgent, spinner) {
52
52
  const { default: stealth } = yield Promise.resolve().then(() => __importStar(require('puppeteer-extra-plugin-stealth')));
53
53
  puppeteer.use(stealth());
54
54
  }
55
- spinner === null || spinner === void 0 ? void 0 : spinner.info('Launching Browser');
56
- browser = yield initBrowser(sessionId, config);
57
- const waPage = yield getWAPage(browser);
58
- spinner === null || spinner === void 0 ? void 0 : spinner.info('Setting Up Browser');
55
+ let waPage = _page;
56
+ if (!waPage) {
57
+ spinner === null || spinner === void 0 ? void 0 : spinner.info('Launching Browser');
58
+ browser = yield initBrowser(sessionId, config);
59
+ waPage = yield getWAPage(browser);
60
+ }
61
+ spinner === null || spinner === void 0 ? void 0 : spinner.info('Setting Up Page');
59
62
  if (config === null || config === void 0 ? void 0 : config.proxyServerCredentials) {
60
63
  yield waPage.authenticate(config.proxyServerCredentials);
61
64
  }
@@ -115,40 +118,51 @@ function initPage(sessionId, config, customUserAgent, spinner) {
115
118
  request.continue();
116
119
  }));
117
120
  }
118
- spinner === null || spinner === void 0 ? void 0 : spinner.info('Loading session data');
119
- let sessionjson = getSessionDataFromFile(sessionId, config, spinner);
120
- if (!sessionjson && sessionjson !== "" && config.sessionDataBucketAuth) {
121
- try {
122
- spinner === null || spinner === void 0 ? void 0 : spinner.info('Unable to find session data file locally, attempting to find session data in cloud storage..');
123
- sessionjson = JSON.parse(Buffer.from(yield pico_s3_1.getTextFile(Object.assign(Object.assign({ directory: '_sessionData' }, JSON.parse(Buffer.from(config.sessionDataBucketAuth, 'base64').toString('ascii'))), { filename: `${config.sessionId || 'session'}.data.json` })), 'base64').toString('ascii'));
124
- spinner === null || spinner === void 0 ? void 0 : spinner.succeed('Successfully downloaded session data file from cloud storage!');
125
- }
126
- catch (error) {
127
- spinner === null || spinner === void 0 ? void 0 : spinner.fail(`${error instanceof pico_s3_1.FileNotFoundError ? 'The session data file was not found in the cloud storage bucket' : 'Something went wrong while fetching session data from cloud storage bucket'}. Continuing...`);
128
- }
129
- }
130
- if (sessionjson) {
131
- spinner === null || spinner === void 0 ? void 0 : spinner.info(config.multiDevice ? "multi-device enabled. Session data skipped..." : 'Existing session data detected. Injecting...');
132
- if (!(config === null || config === void 0 ? void 0 : config.multiDevice))
133
- yield waPage.evaluateOnNewDocument(session => {
134
- localStorage.clear();
135
- Object.keys(session).forEach(key => localStorage.setItem(key, session[key]));
136
- }, sessionjson);
137
- spinner === null || spinner === void 0 ? void 0 : spinner.succeed('Existing session data injected');
121
+ if (skipAuth) {
122
+ spinner.info("Skipping Authentication");
138
123
  }
139
124
  else {
140
- if (config === null || config === void 0 ? void 0 : config.multiDevice) {
141
- spinner === null || spinner === void 0 ? void 0 : spinner.info("No session data detected. Opting in for MD.");
142
- spinner === null || spinner === void 0 ? void 0 : spinner.info("Make sure to keep the session alive for at least 5 minutes after scanning the QR code before trying to restart a session!!");
143
- yield waPage.evaluateOnNewDocument(session => {
144
- localStorage.clear();
145
- Object.keys(session).forEach(key => localStorage.setItem(key, session[key]));
146
- }, {
147
- "md-opted-in": "true",
148
- "MdUpgradeWamFlag": "true",
149
- "remember-me": "true"
150
- });
125
+ /**
126
+ * AUTH
127
+ */
128
+ spinner === null || spinner === void 0 ? void 0 : spinner.info('Loading session data');
129
+ let sessionjson = getSessionDataFromFile(sessionId, config, spinner);
130
+ if (!sessionjson && sessionjson !== "" && config.sessionDataBucketAuth) {
131
+ try {
132
+ spinner === null || spinner === void 0 ? void 0 : spinner.info('Unable to find session data file locally, attempting to find session data in cloud storage..');
133
+ sessionjson = JSON.parse(Buffer.from(yield pico_s3_1.getTextFile(Object.assign(Object.assign({ directory: '_sessionData' }, JSON.parse(Buffer.from(config.sessionDataBucketAuth, 'base64').toString('ascii'))), { filename: `${config.sessionId || 'session'}.data.json` })), 'base64').toString('ascii'));
134
+ spinner === null || spinner === void 0 ? void 0 : spinner.succeed('Successfully downloaded session data file from cloud storage!');
135
+ }
136
+ catch (error) {
137
+ spinner === null || spinner === void 0 ? void 0 : spinner.fail(`${error instanceof pico_s3_1.FileNotFoundError ? 'The session data file was not found in the cloud storage bucket' : 'Something went wrong while fetching session data from cloud storage bucket'}. Continuing...`);
138
+ }
139
+ }
140
+ if (sessionjson) {
141
+ spinner === null || spinner === void 0 ? void 0 : spinner.info(config.multiDevice ? "multi-device enabled. Session data skipped..." : 'Existing session data detected. Injecting...');
142
+ if (!(config === null || config === void 0 ? void 0 : config.multiDevice))
143
+ yield waPage.evaluateOnNewDocument(session => {
144
+ localStorage.clear();
145
+ Object.keys(session).forEach(key => localStorage.setItem(key, session[key]));
146
+ }, sessionjson);
147
+ spinner === null || spinner === void 0 ? void 0 : spinner.succeed('Existing session data injected');
148
+ }
149
+ else {
150
+ if (config === null || config === void 0 ? void 0 : config.multiDevice) {
151
+ spinner === null || spinner === void 0 ? void 0 : spinner.info("No session data detected. Opting in for MD.");
152
+ spinner === null || spinner === void 0 ? void 0 : spinner.info("Make sure to keep the session alive for at least 5 minutes after scanning the QR code before trying to restart a session!!");
153
+ yield waPage.evaluateOnNewDocument(session => {
154
+ localStorage.clear();
155
+ Object.keys(session).forEach(key => localStorage.setItem(key, session[key]));
156
+ }, {
157
+ "md-opted-in": "true",
158
+ "MdUpgradeWamFlag": "true",
159
+ "remember-me": "true"
160
+ });
161
+ }
151
162
  }
163
+ /**
164
+ * END AUTH
165
+ */
152
166
  }
153
167
  if ((config === null || config === void 0 ? void 0 : config.proxyServerCredentials) && !(config === null || config === void 0 ? void 0 : config.useNativeProxy)) {
154
168
  yield proxy(waPage, proxyAddr);
@@ -158,7 +158,7 @@ function create(config = {}) {
158
158
  * Check if the IGNORE folder exists, therefore, assume that the session is MD.
159
159
  */
160
160
  const mdDir = config["userDataDir"] || `${(config === null || config === void 0 ? void 0 : config.inDocker) ? '/sessions' : (config === null || config === void 0 ? void 0 : config.sessionDataPath) || '.'}/_IGNORE_${(config === null || config === void 0 ? void 0 : config.sessionId) || 'session'}`;
161
- if (fs.existsSync(mdDir) && !(config === null || config === void 0 ? void 0 : config.multiDevice)) {
161
+ if (process.env.AUTO_MD && fs.existsSync(mdDir) && !(config === null || config === void 0 ? void 0 : config.multiDevice)) {
162
162
  spinner.info(`Multi-Device directory detected. multiDevice set to true.`);
163
163
  config.multiDevice = true;
164
164
  }
@@ -269,7 +269,10 @@ function create(config = {}) {
269
269
  const race = [];
270
270
  race.push(auth_1.smartQr(waPage, config, spinner));
271
271
  if ((config === null || config === void 0 ? void 0 : config.qrTimeout) !== 0) {
272
- race.push(timeout(((config === null || config === void 0 ? void 0 : config.qrTimeout) || 60) * 1000));
272
+ let to = ((config === null || config === void 0 ? void 0 : config.qrTimeout) || 60) * 1000;
273
+ if (config === null || config === void 0 ? void 0 : config.multiDevice)
274
+ to = to * 2;
275
+ race.push(timeout(to));
273
276
  }
274
277
  const result = yield Promise.race(race);
275
278
  if (result === "MULTI_DEVICE_DETECTED" && !(config === null || config === void 0 ? void 0 : config.multiDevice)) {
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@open-wa/wa-automate",
3
- "version": "4.23.15",
3
+ "version": "4.24.0",
4
4
  "licenseCheckUrl": "https://openwa.dev/license-check",
5
5
  "brokenMethodReportUrl": "https://openwa.dev/report-bm",
6
- "patches": "https://cdn.openwa.dev/patches.json",
6
+ "patches": "http://127.0.0.1:5503/functions/patches.json",
7
7
  "stickerUrl": "https://sticker-api.openwa.dev",
8
8
  "description": " 💬 🤖 The most reliable NodeJS whatsapp library for chatbots with advanced features.",
9
9
  "main": "dist/index.js",
@@ -69,6 +69,7 @@
69
69
  "@types/express": "^4.17.11",
70
70
  "@types/fs-extra": "^9.0.11",
71
71
  "@types/line-reader": "0.0.34",
72
+ "@types/localtunnel": "^2.0.1",
72
73
  "@types/marked": "^3.0.0",
73
74
  "@types/mime-types": "^2.1.0",
74
75
  "@types/node": "^16.0.0",
@@ -120,11 +121,11 @@
120
121
  "find-up": "^5.0.0",
121
122
  "fs-extra": "^10.0.0",
122
123
  "get-port": "^5.1.1",
123
- "glob-promise": "^4.2.2",
124
124
  "hasha": "^5.2.0",
125
125
  "image-type": "^4.1.0",
126
126
  "is-url-superb": "^5.0.0",
127
127
  "json5": "^2.2.0",
128
+ "localtunnel": "^2.0.2",
128
129
  "lodash.uniq": "^4.5.0",
129
130
  "meow": "^9.0.0",
130
131
  "node-persist": "^3.1.0",
@@ -154,6 +155,7 @@
154
155
  "swagger-ui-express": "^4.1.4",
155
156
  "tcp-port-used": "^1.0.1",
156
157
  "terminal-link": "^2.1.1",
158
+ "tiny-glob": "^0.2.9",
157
159
  "tree-kill": "^1.2.2",
158
160
  "ts-json-schema-generator": "^0.95.0",
159
161
  "ts-morph": "^12.0.0",