@open-wa/wa-automate 4.76.0 → 5.0.0-alpha.2

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.
Files changed (125) hide show
  1. package/README.md +14 -165
  2. package/dist/cli-runtime-B7_3MM0c.cjs +798 -0
  3. package/dist/cli-runtime-B7_3MM0c.cjs.map +1 -0
  4. package/dist/cli-runtime-CmpYxFCk.d.cts +31 -0
  5. package/dist/cli-runtime-CmpYxFCk.d.cts.map +1 -0
  6. package/dist/cli.cjs +17 -0
  7. package/dist/cli.cjs.map +1 -0
  8. package/dist/cli.d.cts +2 -0
  9. package/dist/index.cjs +224 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.cts +81 -0
  12. package/dist/index.d.cts.map +1 -0
  13. package/package.json +34 -177
  14. package/CNAME +0 -1
  15. package/_tsconfig.docs.json +0 -140
  16. package/bin/config-schema.json +0 -1
  17. package/bin/oas-type-schemas.json +0 -1
  18. package/bin/server.js +0 -45
  19. package/build/build-config-json-for-bin.ts +0 -56
  20. package/build/generate-oas-types.ts +0 -31
  21. package/dist/api/Client.d.ts +0 -2255
  22. package/dist/api/Client.js +0 -4358
  23. package/dist/api/functions/exposed.enum.d.ts +0 -7
  24. package/dist/api/functions/exposed.enum.js +0 -11
  25. package/dist/api/model/aliases.d.ts +0 -110
  26. package/dist/api/model/aliases.js +0 -3
  27. package/dist/api/model/button.d.ts +0 -24
  28. package/dist/api/model/button.js +0 -2
  29. package/dist/api/model/call.d.ts +0 -51
  30. package/dist/api/model/call.js +0 -18
  31. package/dist/api/model/chat.d.ts +0 -221
  32. package/dist/api/model/chat.js +0 -52
  33. package/dist/api/model/config.d.ts +0 -836
  34. package/dist/api/model/config.js +0 -111
  35. package/dist/api/model/contact.d.ts +0 -143
  36. package/dist/api/model/contact.js +0 -2
  37. package/dist/api/model/errors.d.ts +0 -90
  38. package/dist/api/model/errors.js +0 -117
  39. package/dist/api/model/events.d.ts +0 -120
  40. package/dist/api/model/events.js +0 -127
  41. package/dist/api/model/group-metadata.d.ts +0 -124
  42. package/dist/api/model/group-metadata.js +0 -25
  43. package/dist/api/model/id.d.ts +0 -5
  44. package/dist/api/model/id.js +0 -2
  45. package/dist/api/model/index.d.ts +0 -110
  46. package/dist/api/model/index.js +0 -128
  47. package/dist/api/model/label.d.ts +0 -24
  48. package/dist/api/model/label.js +0 -2
  49. package/dist/api/model/media.d.ts +0 -93
  50. package/dist/api/model/media.js +0 -12
  51. package/dist/api/model/message.d.ts +0 -422
  52. package/dist/api/model/message.js +0 -40
  53. package/dist/api/model/product.d.ts +0 -141
  54. package/dist/api/model/product.js +0 -2
  55. package/dist/api/model/reactions.d.ts +0 -76
  56. package/dist/api/model/reactions.js +0 -2
  57. package/dist/api/model/sessionInfo.d.ts +0 -77
  58. package/dist/api/model/sessionInfo.js +0 -2
  59. package/dist/build/build-postman.d.ts +0 -1
  60. package/dist/build/build-postman.js +0 -262
  61. package/dist/cli/cli-options.d.ts +0 -9
  62. package/dist/cli/cli-options.js +0 -289
  63. package/dist/cli/collections.d.ts +0 -2
  64. package/dist/cli/collections.js +0 -251
  65. package/dist/cli/file-utils.d.ts +0 -1
  66. package/dist/cli/file-utils.js +0 -71
  67. package/dist/cli/index.d.ts +0 -1
  68. package/dist/cli/index.js +0 -231
  69. package/dist/cli/integrations/chatwoot.d.ts +0 -49
  70. package/dist/cli/integrations/chatwoot.js +0 -672
  71. package/dist/cli/integrations/cloudflare.d.ts +0 -6
  72. package/dist/cli/integrations/cloudflare.js +0 -76
  73. package/dist/cli/logo.d.ts +0 -1
  74. package/dist/cli/logo.js +0 -49
  75. package/dist/cli/server.d.ts +0 -24
  76. package/dist/cli/server.js +0 -540
  77. package/dist/cli/setup.d.ts +0 -30
  78. package/dist/cli/setup.js +0 -308
  79. package/dist/config/puppeteer.config.d.ts +0 -11
  80. package/dist/config/puppeteer.config.js +0 -65
  81. package/dist/controllers/auth.d.ts +0 -36
  82. package/dist/controllers/auth.js +0 -322
  83. package/dist/controllers/browser.d.ts +0 -17
  84. package/dist/controllers/browser.js +0 -603
  85. package/dist/controllers/events.d.ts +0 -82
  86. package/dist/controllers/events.js +0 -173
  87. package/dist/controllers/init_patch.d.ts +0 -13
  88. package/dist/controllers/init_patch.js +0 -42
  89. package/dist/controllers/initializer.d.ts +0 -22
  90. package/dist/controllers/initializer.js +0 -511
  91. package/dist/controllers/launch_checks.d.ts +0 -8
  92. package/dist/controllers/launch_checks.js +0 -130
  93. package/dist/controllers/patch_manager.d.ts +0 -37
  94. package/dist/controllers/patch_manager.js +0 -231
  95. package/dist/controllers/popup/index.d.ts +0 -3
  96. package/dist/controllers/popup/index.html +0 -168
  97. package/dist/controllers/popup/index.js +0 -148
  98. package/dist/controllers/script_preloader.d.ts +0 -17
  99. package/dist/controllers/script_preloader.js +0 -88
  100. package/dist/index.d.ts +0 -13
  101. package/dist/index.js +0 -36
  102. package/dist/lib/README.md +0 -5
  103. package/dist/lib/base64.js +0 -1
  104. package/dist/lib/hash.js +0 -1
  105. package/dist/lib/jsSha.min.js +0 -1
  106. package/dist/lib/launch.js +0 -1
  107. package/dist/lib/qr.min.js +0 -1
  108. package/dist/lib/wapi.js +0 -2163
  109. package/dist/logging/custom_transport.d.ts +0 -9
  110. package/dist/logging/custom_transport.js +0 -35
  111. package/dist/logging/logging.d.ts +0 -50
  112. package/dist/logging/logging.js +0 -196
  113. package/dist/structures/Collector.d.ts +0 -202
  114. package/dist/structures/Collector.js +0 -391
  115. package/dist/structures/Dialog.d.ts +0 -55
  116. package/dist/structures/Dialog.js +0 -21
  117. package/dist/structures/MessageCollector.d.ts +0 -78
  118. package/dist/structures/MessageCollector.js +0 -145
  119. package/dist/structures/preProcessors.d.ts +0 -58
  120. package/dist/structures/preProcessors.js +0 -181
  121. package/dist/utils/pid_utils.d.ts +0 -1
  122. package/dist/utils/pid_utils.js +0 -26
  123. package/dist/utils/tools.d.ts +0 -152
  124. package/dist/utils/tools.js +0 -494
  125. package/tos.md +0 -77
@@ -1,4358 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
- var __rest = (this && this.__rest) || function (s, e) {
35
- var t = {};
36
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
37
- t[p] = s[p];
38
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
39
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
40
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
41
- t[p[i]] = s[p[i]];
42
- }
43
- return t;
44
- };
45
- var __importDefault = (this && this.__importDefault) || function (mod) {
46
- return (mod && mod.__esModule) ? mod : { "default": mod };
47
- };
48
- Object.defineProperty(exports, "__esModule", { value: true });
49
- exports.useragent = exports.Client = exports.namespace = void 0;
50
- const mime_types_1 = __importDefault(require("mime-types"));
51
- const axios_1 = __importDefault(require("axios"));
52
- const puppeteer_config_1 = require("../config/puppeteer.config");
53
- const model_1 = require("./model");
54
- const errors_1 = require("./model/errors");
55
- const p_queue_1 = __importDefault(require("p-queue"));
56
- const events_1 = require("../controllers/events");
57
- const uuid_1 = require("uuid");
58
- const parse_function_1 = __importDefault(require("parse-function"));
59
- const fs = __importStar(require("fs"));
60
- const datauri_1 = __importDefault(require("datauri"));
61
- const is_url_superb_1 = __importDefault(require("is-url-superb"));
62
- const fs_extra_1 = require("fs-extra");
63
- const browser_1 = require("../controllers/browser");
64
- const auth_1 = require("../controllers/auth");
65
- const wa_decrypt_1 = require("@open-wa/wa-decrypt");
66
- const path = __importStar(require("path"));
67
- const media_1 = require("./model/media");
68
- const patch_manager_1 = require("../controllers/patch_manager");
69
- const events_2 = require("./model/events");
70
- const MessageCollector_1 = require("../structures/MessageCollector");
71
- const init_patch_1 = require("../controllers/init_patch");
72
- const preProcessors_1 = require("../structures/preProcessors");
73
- const tools_1 = require("../utils/tools");
74
- const logging_1 = require("../logging/logging");
75
- const pid_utils_1 = require("../utils/pid_utils");
76
- /** @ignore */
77
- const pkg = (0, fs_extra_1.readJsonSync)(path.join(__dirname, '../../package.json'));
78
- var namespace;
79
- (function (namespace) {
80
- namespace["Chat"] = "Chat";
81
- namespace["Msg"] = "Msg";
82
- namespace["Contact"] = "Contact";
83
- namespace["GroupMetadata"] = "GroupMetadata";
84
- })(namespace = exports.namespace || (exports.namespace = {}));
85
- /* eslint-enable */
86
- class Client {
87
- /**
88
- * @ignore
89
- * @param page [Page] [Puppeteer Page]{@link https://pptr.dev/#?product=Puppeteer&version=v2.1.1&show=api-class-page} running WA Web
90
- */
91
- constructor(page, createConfig, sessionInfo) {
92
- this._currentlyBeingKilled = false;
93
- this._refreshing = false;
94
- this._loaded = false;
95
- this._prio = Number.MAX_SAFE_INTEGER;
96
- this._pageListeners = [];
97
- this._registeredPageListeners = [];
98
- this._onLogoutCallbacks = [];
99
- this._queues = {};
100
- this._autoEmojiSet = false;
101
- this._autoEmojiQ = new p_queue_1.default({
102
- concurrency: 1,
103
- intervalCap: 1,
104
- carryoverConcurrencyCount: true
105
- });
106
- this._onLogoutSet = false;
107
- this._preprocIdempotencyCheck = {};
108
- /**
109
- * This is used to track if a listener is already used via webhook. Before, webhooks used to be set once per listener. Now a listener can be set via multiple webhooks, or revoked from a specific webhook.
110
- * For this reason, listeners assigned to a webhook are only set once and map through all possible webhooks to and fire only if the specific listener is assigned.
111
- *
112
- * Note: This would be much simpler if eventMode was the default (and only) listener strategy.
113
- */
114
- this._registeredWebhookListeners = {};
115
- /**
116
- * This exposes a simple express middlware that will allow users to quickly boot up an api based off this client. Checkout demo/index.ts for an example
117
- * How to use the middleware:
118
- *
119
- * ```javascript
120
- *
121
- * import { create } from '@open-wa/wa-automate';
122
- * const express = require('express')
123
- * const app = express()
124
- * app.use(express.json())
125
- * const PORT = 8082;
126
- *
127
- * function start(client){
128
- * app.use(client.middleware()); //or client.middleware(true) if you require the session id to be part of the path (so localhost:8082/sendText beccomes localhost:8082/sessionId/sendText)
129
- * app.listen(PORT, function () {
130
- * console.log(`\n• Listening on port ${PORT}!`);
131
- * });
132
- * ...
133
- * }
134
- *
135
- *
136
- * create({
137
- * sessionId:'session1'
138
- * }).then(start)
139
- *
140
- * ```
141
- *
142
- * All requests need to be `POST` requests. You use the API the same way you would with `client`. The method can be the path or the method param in the post body. The arguments for the method should be properly ordered in the args array in the JSON post body.
143
- *
144
- * Example:
145
- *
146
- * ```javascript
147
- * await client.sendText('4477777777777@c.us','test')
148
- * //returns "true_4477777777777@c.us_3EB0645E623D91006252"
149
- * ```
150
- * as a request with a path:
151
- *
152
- * ```javascript
153
- * const axios = require('axios').default;
154
- * axios.post('localhost:8082/sendText', {
155
- * args: [
156
- * "4477777777777@c.us",
157
- * "test"
158
- * ]
159
- * })
160
- * ```
161
- *
162
- * or as a request without a path:
163
- *
164
- * ```javascript
165
- * const axios = require('axios').default;
166
- * axios.post('localhost:8082', {
167
- * method:'sendText',
168
- * args: [
169
- * "4477777777777@c.us",
170
- * "test"
171
- * ]
172
- * })
173
- * ```
174
- *
175
- * As of 1.9.69, you can also send the argyments as an object with the keys mirroring the paramater names of the relative client functions
176
- *
177
- * Example:
178
- *
179
- * ```javascript
180
- * const axios = require('axios').default;
181
- * axios.post('localhost:8082', {
182
- * method:'sendText',
183
- * args: {
184
- * "to":"4477777777777@c.us",
185
- * "content":"test"
186
- * }
187
- * })
188
- * ```
189
- * @param useSessionIdInPath boolean Set this to true if you want to keep each session in it's own path.
190
- *
191
- * For example, if you have a session with id `host` if you set useSessionIdInPath to true, then all requests will need to be prefixed with the path `host`. E.g `localhost:8082/sendText` becomes `localhost:8082/host/sendText`
192
- */
193
- this.middleware = (useSessionIdInPath = false, PORT) => (req, res, next) => __awaiter(this, void 0, void 0, function* () {
194
- if (useSessionIdInPath && !req.path.includes(this._createConfig.sessionId) && this._createConfig.sessionId !== 'session')
195
- return next();
196
- const methodFromPath = this._createConfig.sessionId && this._createConfig.sessionId !== 'session' && req.path.includes(this._createConfig.sessionId) ? req.path.replace(`/${this._createConfig.sessionId}/`, '') : req.path.replace('/', '');
197
- if (req.get('owa-check-property') && req.get('owa-check-value')) {
198
- const checkProp = req.get('owa-check-property');
199
- const checkValue = req.get('owa-check-value');
200
- const sessionId = this._createConfig.sessionId;
201
- const hostAccountNumber = yield this.getHostNumber();
202
- let checkPassed = false;
203
- switch (checkProp) {
204
- case 'session':
205
- checkPassed = sessionId === checkValue;
206
- break;
207
- case 'number':
208
- checkPassed = hostAccountNumber.includes(checkValue);
209
- break;
210
- }
211
- if (!checkPassed) {
212
- if (PORT)
213
- (0, tools_1.processSendData)({ port: PORT });
214
- return res.status(412).send({
215
- success: false,
216
- error: {
217
- name: 'CHECK_FAILED',
218
- message: `Check FAILED - Are you sure you meant to send the request to this session?`,
219
- data: {
220
- incomingCheckProperty: checkProp,
221
- incomingCheckValue: checkValue,
222
- sessionId,
223
- hostAccountNumber: `${hostAccountNumber.substr(-4)}`
224
- }
225
- }
226
- });
227
- }
228
- }
229
- if (req.method === 'POST') {
230
- const rb = (req === null || req === void 0 ? void 0 : req.body) || {};
231
- let { args } = rb;
232
- const m = (rb === null || rb === void 0 ? void 0 : rb.method) || methodFromPath;
233
- logging_1.log.info(`MDLWR - ${m} : ${JSON.stringify(rb || {})}`);
234
- let methodRequiresArgs = false;
235
- if (args && !Array.isArray(args)) {
236
- const methodArgs = (0, parse_function_1.default)().parse(this[m]).args;
237
- logging_1.log.info(`methodArgs: ${methodArgs}`);
238
- if ((methodArgs === null || methodArgs === void 0 ? void 0 : methodArgs.length) > 0)
239
- methodRequiresArgs = true;
240
- args = methodArgs.map(argName => args[argName]);
241
- }
242
- else if (!args)
243
- args = [];
244
- if (this[m]) {
245
- try {
246
- const response = yield this[m](...args);
247
- let success = true;
248
- if (typeof response == 'string' && (response.startsWith("Error") || response.startsWith("ERROR")))
249
- success = false;
250
- return res.send({
251
- success,
252
- response
253
- });
254
- }
255
- catch (error) {
256
- console.error("middleware -> error", error);
257
- if (methodRequiresArgs && Array.isArray(args))
258
- error.message = `${(req === null || req === void 0 ? void 0 : req.params) ? "Please set arguments in request json body, not in params." : "Args expected, none found."} ${error.message}`;
259
- return res.send({
260
- success: false,
261
- error: {
262
- name: error.name,
263
- message: error.message,
264
- data: error.data
265
- }
266
- });
267
- }
268
- }
269
- return res.status(404).send(`Cannot find method: ${m}`);
270
- }
271
- if (req.method === "GET") {
272
- if (["snapshot", "getSnapshot"].includes(methodFromPath)) {
273
- const snapshot = yield this.getSnapshot();
274
- const snapshotBuffer = Buffer.from(snapshot.split(',')[1], 'base64');
275
- res.writeHead(200, {
276
- 'Content-Type': 'image/png',
277
- 'Content-Length': snapshotBuffer.length
278
- });
279
- return res.end(snapshotBuffer);
280
- }
281
- }
282
- return next();
283
- });
284
- this._page = page;
285
- this._createConfig = createConfig || {};
286
- this._loadedModules = [];
287
- this._sessionInfo = sessionInfo;
288
- this._sessionInfo.INSTANCE_ID = (0, uuid_1.v4)();
289
- this._listeners = {};
290
- this._setOnClose();
291
- }
292
- /**
293
- * @private
294
- *
295
- * DO NOT USE THIS.
296
- *
297
- * Run all tasks to set up client AFTER init is fully completed
298
- */
299
- loaded() {
300
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
301
- return __awaiter(this, void 0, void 0, function* () {
302
- /**
303
- * Wait for internal session to load earlier messages
304
- */
305
- logging_1.log.info('Waiting for internal session to finish syncing');
306
- const syncT = yield (0, tools_1.timePromise)(() => this._page.waitForFunction(() => WAPI.isSessionLoaded(), { timeout: 20000, polling: 50 })).catch(() => 20001);
307
- logging_1.log.info(`Internal session finished syncing in ${syncT}ms`);
308
- if ((_a = this._createConfig) === null || _a === void 0 ? void 0 : _a.eventMode) {
309
- yield this.registerAllSimpleListenersOnEv();
310
- }
311
- this._sessionInfo.PHONE_VERSION = (_c = (_b = (yield this.getMe())) === null || _b === void 0 ? void 0 : _b.phone) === null || _c === void 0 ? void 0 : _c.wa_version;
312
- logging_1.log.info('LOADED', {
313
- PHONE_VERSION: this._sessionInfo.PHONE_VERSION
314
- });
315
- if ((((_d = this._createConfig) === null || _d === void 0 ? void 0 : _d.autoEmoji) === undefined || ((_e = this._createConfig) === null || _e === void 0 ? void 0 : _e.autoEmoji)) && !this._autoEmojiSet) {
316
- const ident = typeof ((_f = this._createConfig) === null || _f === void 0 ? void 0 : _f.autoEmoji) === "string" ? (_g = this._createConfig) === null || _g === void 0 ? void 0 : _g.autoEmoji : ":";
317
- this.onMessage((message) => __awaiter(this, void 0, void 0, function* () {
318
- if ((message === null || message === void 0 ? void 0 : message.body) && message.body.startsWith(ident) && message.body.endsWith(ident)) {
319
- const emojiId = message.body.replace(new RegExp(ident, 'g'), "");
320
- if (!emojiId)
321
- return;
322
- yield this._autoEmojiQ.add(() => __awaiter(this, void 0, void 0, function* () { return this.sendEmoji(message.from, emojiId, message.id).catch(() => { }); }));
323
- }
324
- return message;
325
- }));
326
- this._autoEmojiSet = true;
327
- }
328
- if ((((_h = this._createConfig) === null || _h === void 0 ? void 0 : _h.deleteSessionDataOnLogout) || ((_j = this._createConfig) === null || _j === void 0 ? void 0 : _j.killClientOnLogout)) && !this._onLogoutSet) {
329
- this.onLogout(() => __awaiter(this, void 0, void 0, function* () {
330
- var _k, _l, _o, _q, _r, _s;
331
- yield this.waitAllQEmpty();
332
- yield ((_l = (_k = this._queues) === null || _k === void 0 ? void 0 : _k.onLogout) === null || _l === void 0 ? void 0 : _l.onEmpty());
333
- yield ((_q = (_o = this._queues) === null || _o === void 0 ? void 0 : _o.onLogout) === null || _q === void 0 ? void 0 : _q.onIdle());
334
- yield (0, browser_1.invalidateSesssionData)(this._createConfig);
335
- if ((_r = this._createConfig) === null || _r === void 0 ? void 0 : _r.deleteSessionDataOnLogout)
336
- yield (0, browser_1.deleteSessionData)(this._createConfig);
337
- if ((_s = this._createConfig) === null || _s === void 0 ? void 0 : _s.killClientOnLogout) {
338
- console.log("Session logged out. Killing client");
339
- logging_1.log.warn("Session logged out. Killing client");
340
- this.kill("LOGGED_OUT");
341
- }
342
- }), -1);
343
- this._onLogoutSet = true;
344
- }
345
- this._loaded = true;
346
- });
347
- }
348
- registerAllSimpleListenersOnEv() {
349
- return __awaiter(this, void 0, void 0, function* () {
350
- yield Promise.all(Object.keys(events_2.SimpleListener).map(eventKey => this.registerEv(events_2.SimpleListener[eventKey])));
351
- });
352
- }
353
- getSessionId() {
354
- return this._createConfig.sessionId || 'session';
355
- }
356
- getPage() {
357
- return this._page;
358
- }
359
- _setOnClose() {
360
- this._page.on('close', () => {
361
- var _a;
362
- if (!this._refreshing) {
363
- console.log("Browser page has closed. Killing client");
364
- logging_1.log.warn("Browser page has closed. Killing client");
365
- this.kill("PAGE_CLOSED");
366
- if ((_a = this._createConfig) === null || _a === void 0 ? void 0 : _a.killProcessOnBrowserClose)
367
- process.exit();
368
- }
369
- });
370
- }
371
- _reInjectWapi(newTab) {
372
- return __awaiter(this, void 0, void 0, function* () {
373
- yield (0, browser_1.injectApi)(newTab || this._page, null, true);
374
- });
375
- }
376
- _reRegisterListeners() {
377
- return __awaiter(this, void 0, void 0, function* () {
378
- return Object.keys(this._listeners).forEach((listenerName) => this[listenerName](this._listeners[listenerName]));
379
- });
380
- }
381
- /**
382
- * A convinience method to download the [[DataURL]] of a file
383
- * @param url The url
384
- * @param optionsOverride You can use this to override the [axios request config](https://github.com/axios/axios#request-config)
385
- * @returns `Promise<DataURL>`
386
- */
387
- download(url, optionsOverride = {}) {
388
- return __awaiter(this, void 0, void 0, function* () {
389
- return yield (0, tools_1.getDUrl)(url, optionsOverride);
390
- });
391
- }
392
- /**
393
- * Grab the logger for this session/process
394
- */
395
- logger() {
396
- return logging_1.log;
397
- }
398
- /**
399
- * Refreshes the page and reinjects all necessary files. This may be useful for when trying to save memory
400
- * This will attempt to re register all listeners EXCEPT onLiveLocation and onParticipantChanged
401
- */
402
- refresh() {
403
- var _a, _b, _c, _d;
404
- return __awaiter(this, void 0, void 0, function* () {
405
- this._refreshing = true;
406
- const spinner = new events_1.Spin(((_a = this._createConfig) === null || _a === void 0 ? void 0 : _a.sessionId) || 'session', 'REFRESH', (_b = this._createConfig) === null || _b === void 0 ? void 0 : _b.disableSpins);
407
- const { me } = yield this.getMe();
408
- /**
409
- * preload license
410
- */
411
- const preloadlicense = ((_c = this._createConfig) === null || _c === void 0 ? void 0 : _c.licenseKey) ? yield (0, patch_manager_1.getLicense)(this._createConfig, me, this._sessionInfo, spinner) : false;
412
- spinner.info('Refreshing session');
413
- const START_TIME = Date.now();
414
- spinner.info("Opening session in new tab");
415
- const newTab = yield this._page.browser().newPage();
416
- const qrManager = new auth_1.QRManager(this._createConfig);
417
- yield (0, browser_1.initPage)(this.getSessionId(), this._createConfig, qrManager, this._createConfig.customUserAgent, spinner, newTab, true);
418
- // await newTab.goto(puppeteerConfig.WAUrl);
419
- //Two promises. One that closes the previous page, one that sets up the new page
420
- const closePageOnConflict = () => __awaiter(this, void 0, void 0, function* () {
421
- const useHere = yield this._page.evaluate(() => WAPI.getUseHereString());
422
- spinner.info("Waiting for conflict to close stale tab...");
423
- yield this._page.waitForFunction(`[...document.querySelectorAll("div[role=button")].find(e=>{return e.innerHTML.toLowerCase().includes("${useHere.toLowerCase()}")})`, { timeout: 0, polling: 500 });
424
- yield this._page.goto('about:blank');
425
- spinner.info("Closing stale tab");
426
- yield this._page.close();
427
- spinner.info("Stale tab closed. Switching contexts...");
428
- this._page = newTab;
429
- });
430
- const setupNewPage = () => __awaiter(this, void 0, void 0, function* () {
431
- var _e, _f;
432
- /**
433
- * Wait for the new page to be loaded up before closing existing page
434
- */
435
- spinner.info("Checking if fresh session is authenticated...");
436
- if (yield (0, auth_1.isAuthenticated)(newTab)) {
437
- /**
438
- * Reset all listeners
439
- */
440
- this._registeredEvListeners = {};
441
- // this._listeners = {};
442
- if ((_e = this._createConfig) === null || _e === void 0 ? void 0 : _e.waitForRipeSession) {
443
- yield this._reInjectWapi(newTab);
444
- spinner.start("Waiting for ripe session...");
445
- if (yield (0, auth_1.waitForRipeSession)(newTab))
446
- spinner.succeed("Session ready for injection");
447
- else
448
- spinner.fail("You may experience issues in headless mode. Continuing...");
449
- }
450
- spinner.info("Injected new session...");
451
- yield this._reInjectWapi(newTab);
452
- /**
453
- * patch
454
- */
455
- yield (0, patch_manager_1.getAndInjectLivePatch)(newTab, spinner, null, this._createConfig, this._sessionInfo);
456
- if ((_f = this._createConfig) === null || _f === void 0 ? void 0 : _f.licenseKey)
457
- yield (0, patch_manager_1.getAndInjectLicense)(newTab, this._createConfig, me, this._sessionInfo, spinner, preloadlicense);
458
- /**
459
- * init patch
460
- */
461
- yield (0, init_patch_1.injectInitPatch)(newTab);
462
- }
463
- else
464
- throw new Error("Session Logged Out. Cannot refresh. Please restart the process and scan the qr code.");
465
- });
466
- yield Promise.all([
467
- closePageOnConflict(),
468
- setupNewPage()
469
- ]);
470
- spinner.info("New session live. Setting up...");
471
- spinner.info("Reregistering listeners");
472
- yield this.loaded();
473
- if (!((_d = this._createConfig) === null || _d === void 0 ? void 0 : _d.eventMode))
474
- yield this._reRegisterListeners();
475
- spinner.succeed(`Session refreshed in ${(Date.now() - START_TIME) / 1000}s`);
476
- this._refreshing = false;
477
- spinner.remove();
478
- this._setOnClose();
479
- return true;
480
- });
481
- }
482
- /**
483
- * Get the session info
484
- *
485
- * @returns SessionInfo
486
- */
487
- getSessionInfo() {
488
- return this._sessionInfo;
489
- }
490
- /**
491
- * Easily resize page on the fly. Useful if you're showing screenshots in a web-app.
492
- */
493
- resizePage(width = 1920, height = 1080) {
494
- return __awaiter(this, void 0, void 0, function* () {
495
- yield this._page.setViewport({
496
- width,
497
- height
498
- });
499
- return true;
500
- });
501
- }
502
- /**
503
- * Get the config which was used to set up the client. Sensitive details (like devTools username and password, and browserWSEndpoint) are scrubbed
504
- *
505
- * @returns SessionInfo
506
- */
507
- getConfig() {
508
- /* eslint-disable */
509
- const _a = this._createConfig, { devtools, browserWSEndpoint, sessionData, proxyServerCredentials, restartOnCrash } = _a, rest = __rest(_a, ["devtools", "browserWSEndpoint", "sessionData", "proxyServerCredentials", "restartOnCrash"]);
510
- /* eslint-enable */
511
- return rest;
512
- }
513
- pup(pageFunction, ...args) {
514
- var _a, _b, _c, _d, _e, _f;
515
- return __awaiter(this, void 0, void 0, function* () {
516
- const invocation_id = (0, uuid_1.v4)().slice(-5);
517
- const { safeMode, callTimeout, idCorrection, logging } = this._createConfig;
518
- let _t;
519
- if (safeMode) {
520
- if (!this._page || this._page.isClosed())
521
- throw new errors_1.CustomError(errors_1.ERROR_NAME.PAGE_CLOSED, 'page closed');
522
- const state = yield this.forceUpdateConnectionState();
523
- if (state !== model_1.STATE.CONNECTED)
524
- throw new errors_1.CustomError(errors_1.ERROR_NAME.STATE_ERROR, `state: ${state}`);
525
- }
526
- if (idCorrection && args[0]) {
527
- const fixId = (id) => {
528
- var _a;
529
- let isGroup = false;
530
- let scrubbedId = (_a = id === null || id === void 0 ? void 0 : id.match(/\d|-/g)) === null || _a === void 0 ? void 0 : _a.join('');
531
- scrubbedId = scrubbedId.match(/-/g) && scrubbedId.match(/-/g).length == 1 && scrubbedId.split('-')[1].length === 10 ? scrubbedId : scrubbedId.replace(/-/g, '');
532
- if (scrubbedId.includes('-') || scrubbedId.length === 18)
533
- isGroup = true;
534
- const fixed = isGroup ?
535
- `${scrubbedId === null || scrubbedId === void 0 ? void 0 : scrubbedId.replace(/@(c|g).us/g, '')}@g.us` :
536
- `${scrubbedId === null || scrubbedId === void 0 ? void 0 : scrubbedId.replace(/@(c|g).us/g, '')}@c.us`;
537
- logging_1.log.info('Fixed ID', { id, fixed });
538
- return fixed;
539
- };
540
- if (typeof args[0] === 'string' && args[0] && !(args[0].includes("@g.us") || args[0].includes("@c.us")) && ((_c = (_b = (((_a = pageFunction === null || pageFunction === void 0 ? void 0 : pageFunction.toString()) === null || _a === void 0 ? void 0 : _a.match(/[^(]*\(([^)]*)\)/)[1]) || "")) === null || _b === void 0 ? void 0 : _b.replace(/\s/g, '')) === null || _c === void 0 ? void 0 : _c.split(','))) {
541
- const p = ((pageFunction === null || pageFunction === void 0 ? void 0 : pageFunction.toString().match(/[^(]*\(([^)]*)\)/)[1]) || "").replace(/\s/g, '').split(',');
542
- if (["to", "chatId", "groupChatId", "groupId", "contactId"].includes(p[0]))
543
- args[0] = fixId(args[0]);
544
- }
545
- else if (typeof args[0] === 'object')
546
- Object.entries(args[0]).map(([k, v]) => {
547
- if (["to", "chatId", "groupChatId", "groupId", "contactId"].includes(k) && typeof v == "string" && v && !(v.includes("@g.us") || v.includes("@c.us"))) {
548
- args[0][k] = fixId(v);
549
- }
550
- });
551
- }
552
- if (logging) {
553
- const wapis = (_e = (((_d = pageFunction === null || pageFunction === void 0 ? void 0 : pageFunction.toString()) === null || _d === void 0 ? void 0 : _d.match(/WAPI\.(\w*)\(/g)) || [])) === null || _e === void 0 ? void 0 : _e.map(s => s.replace(/WAPI|\.|\(/g, ''));
554
- _t = Date.now();
555
- const _args = ["string", "number", "boolean"].includes(typeof args[0]) ? args[0] : Object.assign({}, args[0]);
556
- logging_1.log.info(`IN ${invocation_id}`, {
557
- _method: (wapis === null || wapis === void 0 ? void 0 : wapis.length) === 1 ? wapis[0] : wapis,
558
- _args
559
- });
560
- }
561
- if ((_f = this._createConfig) === null || _f === void 0 ? void 0 : _f.aggressiveGarbageCollection) {
562
- const gc = yield this._page.evaluate(() => gc());
563
- }
564
- const mainPromise = this._page.evaluate(pageFunction, ...args);
565
- if (callTimeout)
566
- return yield Promise.race([mainPromise, new Promise((resolve, reject) => { var _a; return setTimeout(reject, (_a = this._createConfig) === null || _a === void 0 ? void 0 : _a.callTimeout, new errors_1.PageEvaluationTimeout()); })]);
567
- const res = yield mainPromise;
568
- if (_t && logging) {
569
- logging_1.log.info(`OUT ${invocation_id}: ${Date.now() - _t}ms`, { res });
570
- }
571
- return this.responseWrap(res);
572
- });
573
- }
574
- responseWrap(res) {
575
- if (this._loaded && typeof res === "string" && res.includes("requires") && res.includes("license")) {
576
- console.info('\x1b[36m', "🔶", res, "🔶", '\x1b[0m');
577
- }
578
- if (this._createConfig.onError && typeof res == "string" && (res.startsWith("Error") || res.startsWith("ERROR"))) {
579
- const e = this._createConfig.onError;
580
- /**
581
- * Log error
582
- */
583
- if (e == model_1.OnError.LOG_AND_FALSE ||
584
- e == model_1.OnError.LOG_AND_STRING ||
585
- res.includes("get.openwa.dev"))
586
- console.error(res);
587
- /**
588
- * Return res
589
- */
590
- if (e == model_1.OnError.AS_STRING ||
591
- e == model_1.OnError.NOTHING ||
592
- e == model_1.OnError.LOG_AND_STRING)
593
- return res;
594
- /**
595
- * Return false
596
- */
597
- if (e == model_1.OnError.LOG_AND_FALSE ||
598
- e == model_1.OnError.RETURN_FALSE)
599
- return false;
600
- if (e == model_1.OnError.RETURN_ERROR)
601
- return new Error(res);
602
- if (e == model_1.OnError.THROW)
603
- throw new Error(res);
604
- }
605
- return res;
606
- }
607
- /**
608
- * //////////////////////// LISTENERS
609
- */
610
- removeListener(listener) {
611
- events_1.ev.removeAllListeners(this.getEventSignature(listener));
612
- return true;
613
- }
614
- removeAllListeners() {
615
- Object.keys(this._registeredEvListeners).map(listener => events_1.ev.removeAllListeners(this.getEventSignature(listener)));
616
- return true;
617
- }
618
- /**
619
- *
620
- */
621
- registerListener(funcName, _fn, queueOptions) {
622
- return __awaiter(this, void 0, void 0, function* () {
623
- let fn;
624
- if (queueOptions) {
625
- if (!this._queues[funcName]) {
626
- this._queues[funcName] = new p_queue_1.default(queueOptions);
627
- }
628
- fn = (data) => __awaiter(this, void 0, void 0, function* () {
629
- return this._queues[funcName].add(() => _fn(data), {
630
- priority: this.tickPriority()
631
- });
632
- });
633
- }
634
- else {
635
- fn = _fn;
636
- }
637
- if (this._registeredEvListeners && this._registeredEvListeners[funcName]) {
638
- return events_1.ev.on(this.getEventSignature(funcName), ({ data }) => fn(data), { objectify: true });
639
- }
640
- /**
641
- * If evMode is on then make the callback come from ev.
642
- */
643
- //add a reference to this callback
644
- const set = () => this.pup(({ funcName }) => {
645
- //@ts-ignore
646
- return window[funcName] ? WAPI[`${funcName}`](obj => window[funcName](obj)) : false;
647
- }, { funcName });
648
- if (this._listeners[funcName] && !this._refreshing) {
649
- return true;
650
- }
651
- this._listeners[funcName] = fn;
652
- /**
653
- * First check if the function is exposed to the page
654
- */
655
- const exists = yield this.pup(({ checkFuncName }) => window[checkFuncName] ? true : false, { checkFuncName: funcName });
656
- /**
657
- * If it is exposed to the page then set the listener to that exposed function
658
- */
659
- if (exists)
660
- return yield set();
661
- const res = yield this._page.exposeFunction(funcName, (obj) => fn(obj)).then(set).catch(() => set);
662
- return res;
663
- });
664
- }
665
- // NON-STANDARD LISTENERS
666
- registerPageEventListener(_event, callback, priority) {
667
- const event = _event;
668
- this._pageListeners.push({
669
- event,
670
- callback,
671
- priority
672
- });
673
- if (this._registeredPageListeners.includes(event))
674
- return true;
675
- this._registeredPageListeners.push(event);
676
- logging_1.log.info(`setting page listener: ${String(event)}`, this._registeredPageListeners);
677
- this._page.on(event, (...args) => __awaiter(this, void 0, void 0, function* () {
678
- yield Promise.all(this._pageListeners.filter(l => l.event === event).filter(({ priority }) => priority !== -1).sort((a, b) => (b.priority || 0) - (a.priority || 0)).map(l => l.callback(...args)));
679
- yield Promise.all(this._pageListeners.filter(l => l.event === event).filter(({ priority }) => priority == -1).sort((a, b) => (b.priority || 0) - (a.priority || 0)).map(l => l.callback(...args)));
680
- return;
681
- }));
682
- }
683
- /**
684
- * It calls the JavaScript garbage collector
685
- * @returns Nothing.
686
- */
687
- gc() {
688
- return __awaiter(this, void 0, void 0, function* () {
689
- yield this._page.evaluate(() => gc());
690
- return;
691
- });
692
- }
693
- /**
694
- * Listens to a log out event
695
- *
696
- * @event
697
- * @param fn callback
698
- * @param priority A priority of -1 will mean the callback will be triggered after all the non -1 callbacks
699
- * @fires `true`
700
- */
701
- onLogout(fn, priority) {
702
- return __awaiter(this, void 0, void 0, function* () {
703
- const event = 'framenavigated';
704
- this._onLogoutCallbacks.push({
705
- callback: fn,
706
- priority
707
- });
708
- if (!this._queues[event])
709
- this._queues[event] = new p_queue_1.default({
710
- concurrency: 1,
711
- intervalCap: 1,
712
- carryoverConcurrencyCount: true
713
- });
714
- if (this._registeredPageListeners.includes(event))
715
- return true;
716
- this.registerPageEventListener(event, (frame) => __awaiter(this, void 0, void 0, function* () {
717
- if (frame.url().includes('post_logout=1')) {
718
- console.log("LOGGED OUT");
719
- logging_1.log.warn("LOGGED OUT");
720
- yield Promise.all(this._onLogoutCallbacks.filter(c => c.priority !== -1).map(({ callback }) => this._queues[event].add(() => callback(true))));
721
- yield this._queues[event].onEmpty();
722
- yield Promise.all(this._onLogoutCallbacks.filter(c => c.priority == -1).map(({ callback }) => this._queues[event].add(() => callback(true))));
723
- yield this._queues[event].onEmpty();
724
- }
725
- }), priority || 1);
726
- return true;
727
- });
728
- }
729
- /**
730
- * Wait for the webhook queue to become idle. This is useful for ensuring webhooks are cleared before ending a process.
731
- */
732
- waitWhQIdle() {
733
- return __awaiter(this, void 0, void 0, function* () {
734
- if (this._webhookQueue) {
735
- return yield this._webhookQueue.onIdle();
736
- }
737
- return true;
738
- });
739
- }
740
- /**
741
- * Wait for all queues to be empty
742
- */
743
- waitAllQEmpty() {
744
- return __awaiter(this, void 0, void 0, function* () {
745
- return yield Promise.all([
746
- this._webhookQueue,
747
- ...Object.values(this._queues)
748
- ].filter(q => q).map(q => q === null || q === void 0 ? void 0 : q.onEmpty()));
749
- return true;
750
- });
751
- }
752
- /**
753
- * If you have set `onAnyMessage` or `onMessage` with the second parameter (PQueue options) then you may want to inspect their respective PQueue's.
754
- */
755
- getListenerQueues() {
756
- return this._queues;
757
- }
758
- // STANDARD SIMPLE LISTENERS
759
- preprocessMessage(message, source) {
760
- return __awaiter(this, void 0, void 0, function* () {
761
- let alreadyProcessed = false;
762
- if (this._preprocIdempotencyCheck[message.id]) {
763
- logging_1.log.info(`preprocessMessage: ${message.id} already being processed`);
764
- // return message;
765
- alreadyProcessed = true;
766
- }
767
- this._preprocIdempotencyCheck[message.id] = true;
768
- let fil = "";
769
- try {
770
- fil = typeof this._createConfig.preprocFilter == "function" ? this._createConfig.preprocFilter : typeof this._createConfig.preprocFilter == "string" ? eval(this._createConfig.preprocFilter || "undefined") : undefined;
771
- }
772
- catch (error) {
773
- //do nothing
774
- }
775
- const m = fil ? [message].filter(typeof fil == "function" ? fil : x => x)[0] : message;
776
- if (m && this._createConfig.messagePreprocessor) {
777
- if (!Array.isArray(this._createConfig.messagePreprocessor))
778
- this._createConfig.messagePreprocessor = [this._createConfig.messagePreprocessor];
779
- /**
780
- * Map/chain over the preprocs and resolve.
781
- *
782
- * Each promise will update the _m value which is just a mutatable message object.
783
- */
784
- let _m = m;
785
- yield Promise.all(this._createConfig.messagePreprocessor.map((preproc, index) => __awaiter(this, void 0, void 0, function* () {
786
- let custom = false;
787
- const start = Date.now();
788
- if (typeof preproc === "function") {
789
- custom = true;
790
- _m = yield preproc(_m, this, alreadyProcessed, source);
791
- }
792
- else if (typeof preproc === "string" && preProcessors_1.MessagePreprocessors[preproc])
793
- _m = yield preProcessors_1.MessagePreprocessors[preproc](_m, this, alreadyProcessed, source);
794
- logging_1.log.info(`Preproc ${custom ? 'CUSTOM' : preproc} ${index} ${fil} ${message.id} ${m.id} ${Date.now() - start}ms`);
795
- return _m;
796
- })));
797
- const preprocres = _m || message;
798
- delete this._preprocIdempotencyCheck[message.id];
799
- return preprocres;
800
- }
801
- delete this._preprocIdempotencyCheck[message.id];
802
- return message;
803
- });
804
- }
805
- /**
806
- * Listens to incoming messages
807
- *
808
- * @event
809
- * @param fn callback
810
- * @param queueOptions PQueue options. Set to `{}` for default PQueue.
811
- * @fires [[Message]]
812
- */
813
- onMessage(fn, queueOptions) {
814
- var _a;
815
- return __awaiter(this, void 0, void 0, function* () {
816
- const _fn = (message) => __awaiter(this, void 0, void 0, function* () { return fn(yield this.preprocessMessage(message, 'onMessage')); });
817
- return this.registerListener(events_2.SimpleListener.Message, _fn, ((_a = this === null || this === void 0 ? void 0 : this._createConfig) === null || _a === void 0 ? void 0 : _a.pQueueDefault) || queueOptions);
818
- });
819
- }
820
- /**
821
- * Listens to all new messages
822
- *
823
- * @event
824
- * @param fn callback
825
- * @param queueOptions PQueue options. Set to `{}` for default PQueue.
826
- * @fires [[Message]]
827
- */
828
- onAnyMessage(fn, queueOptions) {
829
- var _a;
830
- return __awaiter(this, void 0, void 0, function* () {
831
- const _fn = (message) => __awaiter(this, void 0, void 0, function* () { return fn(yield this.preprocessMessage(message, 'onAnyMessage')); });
832
- return this.registerListener(events_2.SimpleListener.AnyMessage, _fn, ((_a = this === null || this === void 0 ? void 0 : this._createConfig) === null || _a === void 0 ? void 0 : _a.pQueueDefault) || queueOptions);
833
- });
834
- }
835
- /**
836
- *
837
- * Listens to when a message is deleted by a recipient or the host account
838
- * @event
839
- * @param fn callback
840
- * @fires [[Message]]
841
- */
842
- onMessageDeleted(fn) {
843
- return __awaiter(this, void 0, void 0, function* () {
844
- return this.registerListener(events_2.SimpleListener.MessageDeleted, fn);
845
- });
846
- }
847
- /**
848
- * Listens to when a chat is deleted by the host account
849
- * @event
850
- * @param fn callback
851
- * @fires [[Chat]]
852
- */
853
- onChatDeleted(fn) {
854
- return __awaiter(this, void 0, void 0, function* () {
855
- return this.registerListener(events_2.SimpleListener.ChatDeleted, fn);
856
- });
857
- }
858
- /**
859
- * Listens to button message responses
860
- * @event
861
- * @param fn callback
862
- * @fires [[Message]]
863
- */
864
- onButton(fn) {
865
- return __awaiter(this, void 0, void 0, function* () {
866
- return this.registerListener(events_2.SimpleListener.Button, fn);
867
- });
868
- }
869
- /**
870
- * Listens to poll vote events
871
- * @event
872
- * @param fn callback
873
- * @fires [[PollData]]
874
- */
875
- onPollVote(fn) {
876
- return __awaiter(this, void 0, void 0, function* () {
877
- return this.registerListener(events_2.SimpleListener.PollVote, fn);
878
- });
879
- }
880
- /**
881
- * Listens to broadcast messages
882
- * @event
883
- * @param fn callback
884
- * @fires [[Message]]
885
- */
886
- onBroadcast(fn) {
887
- return __awaiter(this, void 0, void 0, function* () {
888
- return this.registerListener(events_2.SimpleListener.Broadcast, fn);
889
- });
890
- }
891
- /**
892
- * @deprecated
893
- *
894
- * Listens to battery changes
895
- *
896
- * :::caution
897
- *
898
- * This will most likely not work with multi-device mode (the only remaining mode) since the session is no longer connected to the phone but directly to WA servers.
899
- *
900
- * :::
901
- *
902
- * @event
903
- * @param fn callback
904
- * @fires number
905
- */
906
- onBattery(fn) {
907
- return __awaiter(this, void 0, void 0, function* () {
908
- return this.registerListener(events_2.SimpleListener.Battery, fn);
909
- });
910
- }
911
- /**
912
- * Listens to when host device is plugged/unplugged
913
- * @event
914
- *
915
- * @param fn callback
916
- * @fires boolean true if plugged, false if unplugged
917
- */
918
- onPlugged(fn) {
919
- return __awaiter(this, void 0, void 0, function* () {
920
- return this.registerListener(events_2.SimpleListener.Plugged, fn);
921
- });
922
- }
923
- /**
924
- * {@license:restricted@}
925
- *
926
- * Listens to when a contact posts a new story.
927
- * @event
928
- *
929
- * @param fn callback
930
- * @fires e.g
931
- *
932
- * ```javascript
933
- * {
934
- * from: '123456789@c.us'
935
- * id: 'false_132234234234234@status.broadcast'
936
- * }
937
- * ```
938
- */
939
- onStory(fn) {
940
- return __awaiter(this, void 0, void 0, function* () {
941
- return this.registerListener(events_2.SimpleListener.Story, fn);
942
- });
943
- }
944
- /**
945
- * Listens to changes in state
946
- *
947
- * @event
948
- * @fires STATE observable sream of states
949
- */
950
- onStateChanged(fn) {
951
- return __awaiter(this, void 0, void 0, function* () {
952
- return this.registerListener(events_2.SimpleListener.StateChanged, fn);
953
- });
954
- }
955
- /**
956
- * Listens to new incoming calls
957
- * @event
958
- * @returns Observable stream of call request objects
959
- */
960
- onIncomingCall(fn) {
961
- return __awaiter(this, void 0, void 0, function* () {
962
- return this.registerListener(events_2.SimpleListener.IncomingCall, fn);
963
- });
964
- }
965
- /**
966
- * Listens to changes on call state
967
- * @event
968
- * @returns Observable stream of call objects
969
- */
970
- onCallState(fn) {
971
- return __awaiter(this, void 0, void 0, function* () {
972
- return this.registerListener(events_2.SimpleListener.CallState, fn);
973
- });
974
- }
975
- /**
976
- * Listens to label change events
977
- *
978
- * @event
979
- * @param fn callback
980
- * @fires [[Label]]
981
- */
982
- onLabel(fn) {
983
- return __awaiter(this, void 0, void 0, function* () {
984
- return this.registerListener(events_2.SimpleListener.Label, fn);
985
- });
986
- }
987
- /**
988
- *{@license:insiders@}
989
- *
990
- * Listens to new orders. Only works on business accounts
991
- */
992
- onOrder(fn) {
993
- return __awaiter(this, void 0, void 0, function* () {
994
- return this.registerListener(events_2.SimpleListener.Order, fn);
995
- });
996
- }
997
- /**
998
- *{@license:insiders@}
999
- *
1000
- * Listens to new orders. Only works on business accounts
1001
- */
1002
- onNewProduct(fn) {
1003
- return __awaiter(this, void 0, void 0, function* () {
1004
- return this.registerListener(events_2.SimpleListener.NewProduct, fn);
1005
- });
1006
- }
1007
- /**
1008
- * {@license:insiders@}
1009
- *
1010
- * Listens to reaction add and change events
1011
- *
1012
- * @event
1013
- * @param fn callback
1014
- * @fires [[ReactionEvent]]
1015
- */
1016
- onReaction(fn) {
1017
- return __awaiter(this, void 0, void 0, function* () {
1018
- return this.registerListener(events_2.SimpleListener.Reaction, fn);
1019
- });
1020
- }
1021
- /**
1022
- * {@license:insiders@}
1023
- *
1024
- * Listens to chat state, including when a specific user is recording and typing within a group chat.
1025
- *
1026
- * @event
1027
- *
1028
- * Here is an example of the fired object:
1029
- *
1030
- * @fires
1031
- * ```javascript
1032
- * {
1033
- * "chat": "00000000000-1111111111@g.us", //the chat in which this state is occuring
1034
- * "user": "22222222222@c.us", //the user that is causing this state
1035
- * "state": "composing, //can also be 'available', 'unavailable', 'recording' or 'composing'
1036
- * }
1037
- * ```
1038
- */
1039
- onChatState(fn) {
1040
- return __awaiter(this, void 0, void 0, function* () {
1041
- return this.registerListener(events_2.SimpleListener.ChatState, fn);
1042
- });
1043
- }
1044
- /**
1045
- * Listens to messages acknowledgement Changes
1046
- *
1047
- * @param fn callback function that handles a [[Message]] as the first and only parameter.
1048
- * @event
1049
- * @returns `true` if the callback was registered
1050
- */
1051
- onAck(fn) {
1052
- return __awaiter(this, void 0, void 0, function* () {
1053
- const _fn = (message) => __awaiter(this, void 0, void 0, function* () { return fn(message); });
1054
- return this.registerListener(events_2.SimpleListener.Ack, _fn);
1055
- });
1056
- }
1057
- /**
1058
- * Listens to add and remove events on Groups on a global level. It is memory efficient and doesn't require a specific group id to listen to.
1059
- *
1060
- * @event
1061
- * @param fn callback function that handles a [[ParticipantChangedEventModel]] as the first and only parameter.
1062
- * @returns `true` if the callback was registered
1063
- */
1064
- onGlobalParticipantsChanged(fn) {
1065
- return __awaiter(this, void 0, void 0, function* () {
1066
- return this.registerListener(events_2.SimpleListener.GlobalParticipantsChanged, fn);
1067
- });
1068
- }
1069
- /**
1070
- * Listents to group approval requests. Emits a message object. Use it with `message.isGroupApprovalRequest()` to check if it is a group approval request.
1071
- *
1072
- * @event
1073
- * @param fn callback function that handles a [[Message]] as the first and only parameter.
1074
- * @returns `true` if the callback was registered
1075
- */
1076
- onGroupApprovalRequest(fn) {
1077
- return __awaiter(this, void 0, void 0, function* () {
1078
- return this.registerListener(events_2.SimpleListener.GroupApprovalRequest, fn);
1079
- });
1080
- }
1081
- /**
1082
- * Listens to all group (gp2) events. This can be useful if you want to catch when a group title, subject or picture is changed.
1083
- *
1084
- * @event
1085
- * @param fn callback function that handles a [[ParticipantChangedEventModel]] as the first and only parameter.
1086
- * @returns `true` if the callback was registered
1087
- */
1088
- onGroupChange(fn) {
1089
- return __awaiter(this, void 0, void 0, function* () {
1090
- return this.registerListener(events_2.SimpleListener.GroupChange, fn);
1091
- });
1092
- }
1093
- /**
1094
- * Fires callback with Chat object every time the host phone is added to a group.
1095
- *
1096
- * @event
1097
- * @param fn callback function that handles a [[Chat]] (group chat) as the first and only parameter.
1098
- * @returns `true` if the callback was registered
1099
- */
1100
- onAddedToGroup(fn) {
1101
- return __awaiter(this, void 0, void 0, function* () {
1102
- return this.registerListener(events_2.SimpleListener.AddedToGroup, fn);
1103
- });
1104
- }
1105
- /**
1106
- * {@license:insiders@}
1107
- *
1108
- * Fires callback with Chat object every time the host phone is removed to a group.
1109
- *
1110
- * @event
1111
- * @param fn callback function that handles a [[Chat]] (group chat) as the first and only parameter.
1112
- * @returns `true` if the callback was registered
1113
- */
1114
- onRemovedFromGroup(fn) {
1115
- return __awaiter(this, void 0, void 0, function* () {
1116
- return this.registerListener(events_2.SimpleListener.RemovedFromGroup, fn);
1117
- });
1118
- }
1119
- /**
1120
- * {@license:insiders@}
1121
- *
1122
- * Fires callback with the relevant chat id every time the user clicks on a chat. This will only work in headful mode.
1123
- *
1124
- * @event
1125
- * @param fn callback function that handles a [[ChatId]] as the first and only parameter.
1126
- * @returns `true` if the callback was registered
1127
- */
1128
- onChatOpened(fn) {
1129
- return __awaiter(this, void 0, void 0, function* () {
1130
- return this.registerListener(events_2.SimpleListener.ChatOpened, fn);
1131
- });
1132
- }
1133
- /**
1134
- * {@license:insiders@}
1135
- *
1136
- * Fires callback with contact id when a new contact is added on the host phone.
1137
- *
1138
- * @event
1139
- * @param fn callback function that handles a [[Chat]] as the first and only parameter.
1140
- * @returns `true` if the callback was registered
1141
- */
1142
- onContactAdded(fn) {
1143
- return __awaiter(this, void 0, void 0, function* () {
1144
- return this.registerListener(events_2.SimpleListener.ChatOpened, fn);
1145
- });
1146
- }
1147
- // COMPLEX LISTENERS
1148
- /**
1149
- * @event
1150
- * Listens to add and remove events on Groups. This can no longer determine who commited the action and only reports the following events add, remove, promote, demote
1151
- * @param groupId group id: xxxxx-yyyy@c.us
1152
- * @param fn callback
1153
- * @returns Observable stream of participantChangedEvent
1154
- */
1155
- onParticipantsChanged(groupId, fn, legacy = false) {
1156
- return __awaiter(this, void 0, void 0, function* () {
1157
- const funcName = "onParticipantsChanged_" + groupId.replace('_', "").replace('_', "");
1158
- return this._page.exposeFunction(funcName, (participantChangedEvent) => fn(participantChangedEvent))
1159
- .then(() => this.pup(({ groupId, funcName, legacy }) => {
1160
- //@ts-ignore
1161
- if (legacy)
1162
- return WAPI._onParticipantsChanged(groupId, window[funcName]);
1163
- else
1164
- return WAPI.onParticipantsChanged(groupId, window[funcName]);
1165
- }, { groupId, funcName, legacy }));
1166
- });
1167
- }
1168
- /**
1169
- * @event Listens to live locations from a chat that already has valid live locations
1170
- * @param chatId the chat from which you want to subscribes to live location updates
1171
- * @param fn callback that takes in a LiveLocationChangedEvent
1172
- * @returns boolean, if returns false then there were no valid live locations in the chat of chatId
1173
- * @emits `<LiveLocationChangedEvent>` LiveLocationChangedEvent
1174
- */
1175
- onLiveLocation(chatId, fn) {
1176
- return __awaiter(this, void 0, void 0, function* () {
1177
- const funcName = "onLiveLocation_" + chatId.replace('_', "").replace('_', "");
1178
- return this._page.exposeFunction(funcName, (liveLocationChangedEvent) => fn(liveLocationChangedEvent))
1179
- .then(() => this.pup(({ chatId, funcName }) => {
1180
- //@ts-ignore
1181
- return WAPI.onLiveLocation(chatId, window[funcName]);
1182
- }, { chatId, funcName }));
1183
- });
1184
- }
1185
- /**
1186
- * Use this simple command to test firing callback events.
1187
- *
1188
- * @param callbackToTest
1189
- * @param testData
1190
- * @returns `false` if the callback was not registered/does not exist
1191
- */
1192
- testCallback(callbackToTest, testData) {
1193
- return __awaiter(this, void 0, void 0, function* () {
1194
- return this.pup(({ callbackToTest, testData }) => {
1195
- return WAPI.testCallback(callbackToTest, testData);
1196
- }, { callbackToTest, testData });
1197
- });
1198
- }
1199
- /**
1200
- * Set presence to available or unavailable.
1201
- * @param available if true it will set your presence to 'online', false will set to unavailable (i.e no 'online' on recipients' phone);
1202
- */
1203
- setPresence(available) {
1204
- return __awaiter(this, void 0, void 0, function* () {
1205
- return yield this.pup(available => WAPI.setPresence(available), available);
1206
- });
1207
- }
1208
- /**
1209
- * set your about me
1210
- * @param newStatus String new profile status
1211
- */
1212
- setMyStatus(newStatus) {
1213
- return __awaiter(this, void 0, void 0, function* () {
1214
- return yield this.pup(({ newStatus }) => WAPI.setMyStatus(newStatus), { newStatus });
1215
- });
1216
- }
1217
- /**
1218
- * {@license:insiders@}
1219
- *
1220
- * Adds label from chat, message or contact. Only for business accounts.
1221
- * @param label: The desired text of the new label. id will be something simple like anhy nnumber from 1-10, name is the label of the label if that makes sense.
1222
- * @returns `false` if something went wrong, or the id (usually a number as a string) of the new label (for example `"58"`)
1223
- */
1224
- createLabel(label) {
1225
- return __awaiter(this, void 0, void 0, function* () {
1226
- return yield this.pup(({ label }) => WAPI.createLabel(label), { label });
1227
- });
1228
- }
1229
- /**
1230
- * Adds label from chat, message or contact. Only for business accounts.
1231
- * @param label: either the id or the name of the label. id will be something simple like anhy nnumber from 1-10, name is the label of the label if that makes sense.
1232
- * @param id The Chat, message or contact id to which you want to add a label
1233
- */
1234
- addLabel(label, chatId) {
1235
- return __awaiter(this, void 0, void 0, function* () {
1236
- return yield this.pup(({ label, chatId }) => WAPI.addOrRemoveLabels(label, chatId, 'add'), { label, chatId });
1237
- });
1238
- }
1239
- /**
1240
- * Returns all labels and the corresponding tagged items.
1241
- */
1242
- getAllLabels() {
1243
- return __awaiter(this, void 0, void 0, function* () {
1244
- return yield this.pup(() => WAPI.getAllLabels());
1245
- });
1246
- }
1247
- /**
1248
- * Removes label from chat, message or contact. Only for business accounts.
1249
- * @param label: either the id or the name of the label. id will be something simple like anhy nnumber from 1-10, name is the label of the label if that makes sense.
1250
- * @param id The Chat, message or contact id to which you want to add a label
1251
- */
1252
- removeLabel(label, chatId) {
1253
- return __awaiter(this, void 0, void 0, function* () {
1254
- return yield this.pup(({ label, chatId }) => WAPI.addOrRemoveLabels(label, chatId, 'remove'), { label, chatId });
1255
- });
1256
- }
1257
- /**
1258
- * Get an array of chats that match the label parameter. For example, if you want to get an array of chat objects that have the label "New customer".
1259
- *
1260
- * This method is case insenstive and only works on business host accounts.
1261
- *
1262
- * @label The label name
1263
- */
1264
- getChatsByLabel(label) {
1265
- return __awaiter(this, void 0, void 0, function* () {
1266
- const res = yield this.pup(({ label }) => WAPI.getChatsByLabel(label), { label });
1267
- if (typeof res == 'string')
1268
- new errors_1.CustomError(errors_1.ERROR_NAME.INVALID_LABEL, res);
1269
- return res;
1270
- });
1271
- }
1272
- /**
1273
- * Send VCARD
1274
- *
1275
- * @param {string} chatId '000000000000@c.us'
1276
- * @param {string} vcard vcard as a string, you can send multiple contacts vcard also.
1277
- * @param {string} contactName The display name for the contact. Ignored on multiple vcards
1278
- * @param {string} contactNumber If supplied, this will be injected into the vcard (VERSION 3 ONLY FROM VCARDJS) with the WA id to make it show up with the correct buttons on WA. The format of this param should be including country code, without any other formating. e.g:
1279
- * `4477777777777`
1280
- * Ignored on multiple vcards
1281
- */
1282
- sendVCard(chatId, vcard, contactName, contactNumber) {
1283
- return __awaiter(this, void 0, void 0, function* () {
1284
- return yield this.pup(({ chatId, vcard, contactName, contactNumber }) => WAPI.sendVCard(chatId, vcard, contactName, contactNumber), { chatId, vcard, contactName, contactNumber });
1285
- });
1286
- }
1287
- /**
1288
- * Set your profile name
1289
- *
1290
- * Please note, this does not work on business accounts!
1291
- *
1292
- * @param newName String new name to set for your profile
1293
- */
1294
- setMyName(newName) {
1295
- return __awaiter(this, void 0, void 0, function* () {
1296
- return yield this.pup(({ newName }) => WAPI.setMyName(newName), { newName });
1297
- });
1298
- }
1299
- /**
1300
- * Sets the chat state
1301
- * @param {ChatState|0|1|2} chatState The state you want to set for the chat. Can be TYPING (0), RECRDING (1) or PAUSED (2).
1302
- * @param {String} chatId
1303
- */
1304
- setChatState(chatState, chatId) {
1305
- return __awaiter(this, void 0, void 0, function* () {
1306
- return yield this.pup(({ chatState, chatId }) => WAPI.setChatState(chatState, chatId),
1307
- //@ts-ignore
1308
- { chatState, chatId });
1309
- });
1310
- }
1311
- /**
1312
- * Returns the connection state
1313
- */
1314
- getConnectionState() {
1315
- return __awaiter(this, void 0, void 0, function* () {
1316
- return yield this._page.evaluate(() => WAPI.getState());
1317
- });
1318
- }
1319
- /**
1320
- * Retreive an array of messages that are not yet sent to the recipient via the host account device (i.e no ticks)
1321
- */
1322
- getUnsentMessages() {
1323
- return __awaiter(this, void 0, void 0, function* () {
1324
- return yield this._page.evaluate(() => WAPI.getUnsentMessages());
1325
- });
1326
- }
1327
- /**
1328
- * Forces the session to update the connection state.
1329
- * @param killBeforeAttemptingToReconnect Setting this to true will force the session to drop the current socket connection before attempting to reconnect. This is useful if you want to force the session to reconnect immediately.
1330
- * @returns updated connection state
1331
- */
1332
- forceUpdateConnectionState(killBeforeReconnect) {
1333
- return __awaiter(this, void 0, void 0, function* () {
1334
- return yield this._page.evaluate((killBeforeReconnect) => WAPI.forceUpdateConnectionState(killBeforeReconnect), killBeforeReconnect);
1335
- });
1336
- }
1337
- /**
1338
- * Returns a list of contact with whom the host number has an existing chat who are also not contacts.
1339
- */
1340
- getChatWithNonContacts() {
1341
- return __awaiter(this, void 0, void 0, function* () {
1342
- return yield this._page.evaluate(() => WAPI.getChatWithNonContacts());
1343
- });
1344
- }
1345
- /**
1346
- * Shuts down the page and browser
1347
- * @returns true
1348
- */
1349
- kill(reason = "MANUALLY_KILLED") {
1350
- var _a, _b;
1351
- return __awaiter(this, void 0, void 0, function* () {
1352
- if (this._currentlyBeingKilled)
1353
- return;
1354
- this._currentlyBeingKilled = true;
1355
- console.log(`Killing client. Shutting Down: ${reason}`);
1356
- logging_1.log.info(`Killing client. Shutting Down: ${reason}`);
1357
- const browser = yield ((_a = this === null || this === void 0 ? void 0 : this._page) === null || _a === void 0 ? void 0 : _a.browser());
1358
- const pid = (browser === null || browser === void 0 ? void 0 : browser.process()) ? (_b = browser === null || browser === void 0 ? void 0 : browser.process()) === null || _b === void 0 ? void 0 : _b.pid : null;
1359
- try {
1360
- yield (0, browser_1.kill)(this._page, browser, false, pid, reason);
1361
- }
1362
- catch (error) {
1363
- //ignore error
1364
- }
1365
- this._currentlyBeingKilled = false;
1366
- return true;
1367
- });
1368
- }
1369
- /**
1370
- * This is a convinient method to click the `Use Here` button in the WA web session.
1371
- *
1372
- * Use this when [[STATE]] is `CONFLICT`. You can read more about managing state here:
1373
- *
1374
- * [[Detecting Logouts]]
1375
- */
1376
- forceRefocus() {
1377
- return __awaiter(this, void 0, void 0, function* () {
1378
- const useHere = yield this._page.evaluate(() => WAPI.getUseHereString());
1379
- yield this._page.waitForFunction(`[...document.querySelectorAll("div[role=button")].find(e=>{return e.innerHTML.toLowerCase().includes("${useHere.toLowerCase()}")})`, { timeout: 0 });
1380
- yield this._page.evaluate(`[...document.querySelectorAll("div[role=button")].find(e=>{return e.innerHTML.toLowerCase().includes("${useHere.toLowerCase()}")}).click()`);
1381
- return true;
1382
- });
1383
- }
1384
- /**
1385
- * Check if the "Phone not Cconnected" message is showing in the browser. If it is showing, then this will return `true`.
1386
- *
1387
- * @returns `boolean`
1388
- */
1389
- isPhoneDisconnected() {
1390
- return __awaiter(this, void 0, void 0, function* () {
1391
- const phoneNotConnected = yield this._page.evaluate(() => WAPI.getLocaledString('active Internet connection'));
1392
- //@ts-ignore
1393
- return yield this.pup(`!![...document.querySelectorAll("div")].find(e=>{return e.innerHTML.toLowerCase().includes("${phoneNotConnected.toLowerCase()}")})`);
1394
- });
1395
- }
1396
- /**
1397
- * Runs a health check to help you determine if/when is an appropiate time to restart/refresh the session.
1398
- */
1399
- healthCheck() {
1400
- return __awaiter(this, void 0, void 0, function* () {
1401
- return yield this._page.evaluate(() => WAPI.healthCheck());
1402
- });
1403
- }
1404
- /**
1405
- * Get the stats of the current process and the corresponding browser process.
1406
- */
1407
- getProcessStats() {
1408
- return __awaiter(this, void 0, void 0, function* () {
1409
- return yield (0, pid_utils_1.pidTreeUsage)([process.pid, this._page.browser().process().pid]);
1410
- });
1411
- }
1412
- /**
1413
- * A list of participants in the chat who have their live location on. If the chat does not exist, or the chat does not have any contacts actively sharing their live locations, it will return false. If it's a chat with a single contact, there will be only 1 value in the array if the contact has their livelocation on.
1414
- * Please note. This should only be called once every 30 or so seconds. This forces the phone to grab the latest live location data for the number. This can be used in conjunction with onLiveLocation (this will trigger onLiveLocation).
1415
- * @param chatId string Id of the chat you want to force the phone to get the livelocation data for.
1416
- * @returns `Promise<LiveLocationChangedEvent []>` | boolean
1417
- */
1418
- forceUpdateLiveLocation(chatId) {
1419
- return __awaiter(this, void 0, void 0, function* () {
1420
- return yield this.pup(({ chatId }) => WAPI.forceUpdateLiveLocation(chatId), { chatId });
1421
- });
1422
- }
1423
- /**
1424
- *
1425
- * @deprecated
1426
- *
1427
- * :::danger
1428
- *
1429
- * Buttons are broken for the foreseeable future. Please DO NOT get a license solely for access to buttons. They are no longer reliable due to recent changes at WA.
1430
- *
1431
- * :::
1432
- *
1433
- * Test the button commands on MD accounts with an insiders key. This is a temporary feature to help fix issue #2658
1434
- */
1435
- testButtons(chatId) {
1436
- return __awaiter(this, void 0, void 0, function* () {
1437
- return yield this.pup(({ chatId }) => WAPI.testButtons(chatId), { chatId });
1438
- });
1439
- }
1440
- link(params) {
1441
- var _a;
1442
- return __awaiter(this, void 0, void 0, function* () {
1443
- const _p = [(_a = this._createConfig) === null || _a === void 0 ? void 0 : _a.linkParams, params].filter(x => x).join('&');
1444
- return `https://get.openwa.dev/l/${yield this.getHostNumber()}${_p ? `?${_p}` : ''}`;
1445
- });
1446
- }
1447
- /**
1448
- * Generate a license link
1449
- */
1450
- getLicenseLink(params) {
1451
- return __awaiter(this, void 0, void 0, function* () {
1452
- return yield this.link(params);
1453
- });
1454
- }
1455
- /**
1456
- *
1457
- * {@license:restricted@}
1458
- *
1459
- * Sends a text message to given chat
1460
- *
1461
- * A license is **NOT** required to send messages with existing chats/contacts. A license is only required for starting conversations with new numbers.
1462
- *
1463
- * @param to chat id: `xxxxx@c.us`
1464
- * @param content text message
1465
- */
1466
- sendText(to, content) {
1467
- return __awaiter(this, void 0, void 0, function* () {
1468
- if (!content)
1469
- content = '';
1470
- if (typeof content !== 'string')
1471
- content = String(content);
1472
- const err = [
1473
- 'Not able to send message to broadcast',
1474
- 'Not a contact',
1475
- 'Error: Number not linked to WhatsApp Account',
1476
- 'ERROR: Please make sure you have at least one chat'
1477
- ];
1478
- content = (content === null || content === void 0 ? void 0 : content.trim()) || content;
1479
- const res = yield this.pup(({ to, content }) => {
1480
- WAPI.sendSeen(to);
1481
- return WAPI.sendMessage(to, content);
1482
- }, { to, content });
1483
- if (err.includes(res)) {
1484
- let msg = res;
1485
- if (res == err[1])
1486
- msg = `ERROR: ${res}. Unlock this feature and support open-wa by getting a license: ${yield this.link()}`;
1487
- console.error(`\n${msg}\n`);
1488
- return this.responseWrap(msg);
1489
- }
1490
- return (err.includes(res) ? false : res);
1491
- });
1492
- }
1493
- /**
1494
- * Sends a text message to given chat that includes mentions.
1495
- * In order to use this method correctly you will need to send the text like this:
1496
- * "@4474747474747 how are you?"
1497
- * Basically, add a @ symbol before the number of the contact you want to mention.
1498
- *
1499
- * @param to chat id: `xxxxx@c.us`
1500
- * @param content text message
1501
- * @param hideTags Removes all tags within the message
1502
- * @param mentions You can optionally add an array of contact IDs to tag only specific people
1503
- */
1504
- sendTextWithMentions(to, content, hideTags, mentions) {
1505
- return __awaiter(this, void 0, void 0, function* () {
1506
- //remove all @c.us from the content
1507
- content = content.replace(/@c.us/, "");
1508
- return yield this.pup(({ to, content, hideTags, mentions }) => {
1509
- WAPI.sendSeen(to);
1510
- return WAPI.sendMessageWithMentions(to, content, hideTags, mentions);
1511
- }, { to, content, hideTags, mentions });
1512
- });
1513
- }
1514
- /**
1515
- * NOTE: This is experimental, most accounts do not have access to this feature in their apps.
1516
- *
1517
- * Edit an existing message
1518
- *
1519
- * @param messageId The message ID to edit
1520
- * @param text The new text content
1521
- * @returns
1522
- */
1523
- editMessage(messageId, text) {
1524
- return __awaiter(this, void 0, void 0, function* () {
1525
- return yield this.pup(({ messageId, text }) => {
1526
- return WAPI.editMessage(messageId, text);
1527
- }, { messageId, text });
1528
- });
1529
- }
1530
- /**
1531
- * [UNTESTED - REQUIRES FEEDBACK]
1532
- * Sends a payment request message to given chat
1533
- *
1534
- * @param to chat id: `xxxxx@c.us`
1535
- * @param amount number the amount to request in 1000 format (e.g £10 => 10000)
1536
- * @param currency string The 3 letter currency code
1537
- * @param message string optional message to send with the payment request
1538
- */
1539
- sendPaymentRequest(to, amount, currency, message) {
1540
- return __awaiter(this, void 0, void 0, function* () {
1541
- return yield this.pup(({ to, amount, currency, message }) => {
1542
- return WAPI.sendPaymentRequest(to, amount, currency, message);
1543
- }, { to, amount, currency, message });
1544
- });
1545
- }
1546
- /**
1547
- *
1548
- * @deprecated
1549
- *
1550
- * :::danger
1551
- *
1552
- * WA BIZ accounts CANNOT send buttons. This is a WA limitation. DO NOT get a license solely for access to buttons on wa business accounts.
1553
- * THIS IS NOT WORKING FOR GROUPS YET.
1554
- *
1555
- * BUTTONS ARE DEPRECATED FOR NOW. DO NOT GET A LICENSE TO USE BUTTONS.
1556
- *
1557
- * :::
1558
- *
1559
- * Send generic quick reply buttons. This is an insiders feature for MD accounts.
1560
- *
1561
- * @param {ChatId} to chat id
1562
- * @param {string | LocationButtonBody} body The body of the buttons message
1563
- * @param {Button[]} buttons Array of buttons - limit is 3!
1564
- * @param {string} title The title/header of the buttons message
1565
- * @param {string} footer The footer of the buttons message
1566
- */
1567
- sendButtons(to, body, buttons, title, footer) {
1568
- return __awaiter(this, void 0, void 0, function* () {
1569
- return yield this.pup(({ to, body, buttons, title, footer }) => {
1570
- return WAPI.sendButtons(to, body, buttons, title, footer);
1571
- }, { to, body, buttons, title, footer });
1572
- });
1573
- }
1574
- /**
1575
- * @deprecated
1576
- *
1577
- * :::danger
1578
- *
1579
- * Template messages (URL & CALL buttons) are broken for the foreseeable future. Please DO NOT get a license solely for access to URL or CALL buttons. They are no longer reliable due to recent changes at WA.
1580
- * WA BIZ accounts CANNOT send buttons. This is a WA limitation. DO NOT get a license solely for access to buttons on wa business accounts.
1581
- *
1582
- * THIS IS NOT WORKING FOR GROUPS YET.
1583
- *
1584
- * ADVANCED ARE DEPRECATED FOR NOW. DO NOT GET A LICENSE TO USE BUTTONS.
1585
- *
1586
- * :::
1587
- *
1588
- *
1589
- * Send advanced buttons with media body. This is an insiders feature for MD accounts.
1590
- *
1591
- * Body can be location, image, video or document. Buttons can be quick reply, url or call buttons.
1592
- *
1593
- * @param {ChatId} to chat id
1594
- * @param {string | LocationButtonBody} body The body of the buttons message
1595
- * @param {AdvancedButton[]} buttons Array of buttons - limit is 3!
1596
- * @param {string} title The title/header of the buttons message
1597
- * @param {string} footer The footer of the buttons message
1598
- * @param {string} filename Required if body is a file!!
1599
- */
1600
- sendAdvancedButtons(to, body, buttons, text, footer, filename) {
1601
- return __awaiter(this, void 0, void 0, function* () {
1602
- if (typeof body !== "string" && body.lat) {
1603
- //this is a location body
1604
- // eslint-disable-next-line no-self-assign
1605
- body = body;
1606
- }
1607
- else if (typeof body == "string" && !(0, tools_1.isDataURL)(body) && !(0, tools_1.isBase64)(body) && !body.includes("data:")) {
1608
- //must be a file then
1609
- const relativePath = path.join(path.resolve(process.cwd(), body || ''));
1610
- if (typeof body == "string" && fs.existsSync(body) || fs.existsSync(relativePath)) {
1611
- body = yield (0, datauri_1.default)(fs.existsSync(body) ? body : relativePath);
1612
- }
1613
- else if (typeof body == "string" && (0, is_url_superb_1.default)(body)) {
1614
- body = yield (0, tools_1.getDUrl)(body);
1615
- }
1616
- else
1617
- throw new errors_1.CustomError(errors_1.ERROR_NAME.FILE_NOT_FOUND, `Cannot find file. Make sure the file reference is relative, a valid URL or a valid DataURL: ${body.slice(0, 25)}`);
1618
- }
1619
- else if (typeof body == "string" && (body.includes("data:") && body.includes("undefined") || body.includes("application/octet-stream") && filename && mime_types_1.default.lookup(filename))) {
1620
- body = `data:${mime_types_1.default.lookup(filename)};base64,${body.split(',')[1]}`;
1621
- }
1622
- return yield this.pup(({ to, body, buttons, text, footer, filename }) => {
1623
- return WAPI.sendAdvancedButtons(to, body, buttons, text, footer, filename);
1624
- }, { to, body, buttons, text, footer, filename });
1625
- });
1626
- }
1627
- /**
1628
- * Send a banner image
1629
- *
1630
- * Note this is a bit of hack on top of a location message. During testing it is shown to not work on iPhones.
1631
- *
1632
- * @param {ChatId} to
1633
- * @param {Base64} base64 base64 encoded jpeg
1634
- */
1635
- sendBanner(to, base64) {
1636
- return __awaiter(this, void 0, void 0, function* () {
1637
- return yield this.pup(({ to, base64 }) => {
1638
- return WAPI.sendBanner(to, base64);
1639
- }, { to, base64 });
1640
- });
1641
- }
1642
- /**
1643
- *
1644
- * @deprecated
1645
- *
1646
- * :::danger
1647
- *
1648
- * It is not currently possible to send a listmessage to a group chat. This is a WA limitation.
1649
- * Please DO NOT get a license solely for access to list messages in group chats.
1650
- *
1651
- * LIST MESSAGES ARE DEPRECATED TILL FURTHER NOTICE
1652
- *
1653
- * :::
1654
- *
1655
- * Send a list message. This will not work when being sent from business accounts!
1656
- *
1657
- * @param {ChatId} to
1658
- * @param {Section[]} sections The Sections of rows for the list message
1659
- * @param {string} title The title of the list message
1660
- * @param {string} description The description of the list message
1661
- * @param {string} actionText The action text of the list message
1662
- */
1663
- sendListMessage(to, sections, title, description, actionText) {
1664
- return __awaiter(this, void 0, void 0, function* () {
1665
- return yield this.pup(({ to, sections, title, description, actionText }) => {
1666
- return WAPI.sendListMessage(to, sections, title, description, actionText);
1667
- }, { to, sections, title, description, actionText });
1668
- });
1669
- }
1670
- /**
1671
- * Sends a reply to given chat that includes mentions, replying to the provided replyMessageId.
1672
- * In order to use this method correctly you will need to send the text like this:
1673
- * "@4474747474747 how are you?"
1674
- * Basically, add a @ symbol before the number of the contact you want to mention.
1675
- * @param to chat id: `xxxxx@c.us`
1676
- * @param content text message
1677
- * @param replyMessageId id of message to reply to
1678
- * @param hideTags Removes all tags within the message
1679
- * @param mentions You can optionally add an array of contact IDs to tag only specific people
1680
- */
1681
- sendReplyWithMentions(to, content, replyMessageId, hideTags, mentions) {
1682
- return __awaiter(this, void 0, void 0, function* () {
1683
- //remove all @c.us from the content
1684
- content = content.replace(/@c.us/, "");
1685
- return yield this.pup(({ to, content, replyMessageId, hideTags, mentions }) => {
1686
- WAPI.sendSeen(to);
1687
- return WAPI.sendReplyWithMentions(to, content, replyMessageId, hideTags, mentions);
1688
- }, { to, content, replyMessageId, hideTags, mentions });
1689
- });
1690
- }
1691
- /**
1692
- * {@license:insiders@}
1693
- *
1694
- * Tags everyone in the group with a message
1695
- *
1696
- * @param groupId group chat id: `xxxxx@g.us`
1697
- * @param content text message to add under all of the tags
1698
- * @param hideTags Removes all tags within the message
1699
- * @param formatting The formatting of the tags. Use @mention to indicate the actual tag. @default `@mention `
1700
- * @param messageBeforeTags set to `true` to show the message before all of the tags
1701
- * @returns `Promise<MessageId>`
1702
- */
1703
- tagEveryone(groupId, content, hideTags, formatting, messageBeforeTags) {
1704
- return __awaiter(this, void 0, void 0, function* () {
1705
- return yield this.pup(({ groupId, content, hideTags, formatting, messageBeforeTags }) => WAPI.tagEveryone(groupId, content, hideTags, formatting, messageBeforeTags), { groupId, content, hideTags, formatting, messageBeforeTags });
1706
- });
1707
- }
1708
- /**
1709
- * Sends a link to a chat that includes a link preview.
1710
- * @param thumb The base 64 data of the image you want to use as the thunbnail. This should be no more than 200x200px. Note: Dont need data url on this param
1711
- * @param url The link you want to send
1712
- * @param title The title of the link
1713
- * @param description The long description of the link preview
1714
- * @param text The text you want to inslude in the message section. THIS HAS TO INCLUDE THE URL otherwise the url will be prepended to the text automatically.
1715
- * @param chatId The chat you want to send this message to.
1716
- * @param quotedMsgId [INSIDERS] Send this link preview message in response to a given quoted message
1717
- * @param customSize [INSIDERS] Anchor the size of the thumbnail
1718
- */
1719
- sendMessageWithThumb(thumb, url, title, description, text, chatId, quotedMsgId, customSize) {
1720
- return __awaiter(this, void 0, void 0, function* () {
1721
- return yield this.pup(({ thumb, url, title, description, text, chatId, quotedMsgId, customSize }) => {
1722
- WAPI.sendMessageWithThumb(thumb, url, title, description, text, chatId, quotedMsgId, customSize);
1723
- }, {
1724
- thumb,
1725
- url,
1726
- title,
1727
- description,
1728
- text,
1729
- chatId,
1730
- quotedMsgId,
1731
- customSize
1732
- });
1733
- });
1734
- }
1735
- /**
1736
- * Note: `address` and `url` are parameters available to insiders only.
1737
- *
1738
- * Sends a location message to given chat
1739
- * @param to chat id: `xxxxx@c.us`
1740
- * @param lat latitude: '51.5074'
1741
- * @param lng longitude: '0.1278'
1742
- * @param loc location text: 'LONDON!'
1743
- * @param address address text: '1 Regents Park!'
1744
- * @param url address text link: 'https://example.com'
1745
- */
1746
- sendLocation(to, lat, lng, loc, address, url) {
1747
- return __awaiter(this, void 0, void 0, function* () {
1748
- return yield this.pup(({ to, lat, lng, loc, address, url }) => WAPI.sendLocation(to, lat, lng, loc, address, url), { to, lat, lng, loc, address, url });
1749
- });
1750
- }
1751
- /**
1752
- * Get the generated user agent, this is so you can send it to the decryption module.
1753
- * @returns String useragent of wa-web session
1754
- */
1755
- getGeneratedUserAgent(userA) {
1756
- return __awaiter(this, void 0, void 0, function* () {
1757
- const ua = userA || puppeteer_config_1.useragent;
1758
- return yield this.pup(({ ua }) => WAPI.getGeneratedUserAgent(ua), { ua });
1759
- });
1760
- }
1761
- /**
1762
- * Decrypts a media message.
1763
- * @param message This can be the serialized [[MessageId]] or the whole [[Message]] object. It is advised to just use the serialized message ID.
1764
- * @returns `Promise<[[DataURL]]>`
1765
- */
1766
- decryptMedia(message) {
1767
- return __awaiter(this, void 0, void 0, function* () {
1768
- let m;
1769
- //if it's the message id, get the message
1770
- if (typeof message === "string")
1771
- m = yield this.getMessageById(message);
1772
- else
1773
- m = message;
1774
- if (!m.mimetype)
1775
- throw new errors_1.CustomError(errors_1.ERROR_NAME.NOT_MEDIA, "Not a media message");
1776
- if (m.type == "sticker")
1777
- m = yield this.getStickerDecryptable(m.id);
1778
- //Dont have an insiders license to decrypt stickers
1779
- if (m === false) {
1780
- console.error(`\nUnable to decrypt sticker. Unlock this feature and support open-wa by getting a license: ${yield this.link("v=i")}\n`);
1781
- throw new errors_1.CustomError(errors_1.ERROR_NAME.STICKER_NOT_DECRYPTED, 'Sticker not decrypted');
1782
- }
1783
- const mediaData = yield (0, wa_decrypt_1.decryptMedia)(m);
1784
- return `data:${m.mimetype};base64,${mediaData.toString('base64')}`;
1785
- });
1786
- }
1787
- /**
1788
- * Sends a image to given chat, with caption or not, using base64
1789
- * @param to chat id `xxxxx@c.us`
1790
- * @param file DataURL data:image/xxx;base64,xxx or the RELATIVE (should start with `./` or `../`) path of the file you want to send. With the latest version, you can now set this to a normal URL (for example [GET] `https://file-examples-com.github.io/uploads/2017/10/file_example_JPG_2500kB.jpg`).
1791
- * @param filename string xxxxx
1792
- * @param caption string xxxxx
1793
- * @param waitForKey boolean default: false set this to true if you want to wait for the id of the message. By default this is set to false as it will take a few seconds to retrieve to the key of the message and this waiting may not be desirable for the majority of users.
1794
- * @param hideTags boolean default: false [INSIDERS] set this to try silent tag someone in the caption
1795
- * @returns `Promise <boolean | string>` This will either return true or the id of the message. It will return true after 10 seconds even if waitForId is true
1796
- */
1797
- sendImage(to, file, filename, caption, quotedMsgId, waitForId, ptt, withoutPreview, hideTags, viewOnce, requestConfig) {
1798
- return __awaiter(this, void 0, void 0, function* () {
1799
- const err = [
1800
- 'Not able to send message to broadcast',
1801
- 'Not a contact',
1802
- 'Error: Number not linked to WhatsApp Account',
1803
- 'ERROR: Please make sure you have at least one chat'
1804
- ];
1805
- /**
1806
- * TODO: File upload improvements
1807
- * 1. *Create an arbitrary file input element
1808
- * 2. *Take the file parameter and create a tempfile in temp dir
1809
- * 3. Forward the tempfile path to the file input, upload the file to the browser context.
1810
- * 4. Instruct the WAPI.sendImage function to consume the file from the element in step 1.
1811
- * 5. *Destroy the input element from the page (happens in wapi.sendimage)
1812
- * 6. *Unlink/rm the tempfile
1813
- * 7. Return the ID of the WAPI.sendImage function.
1814
- */
1815
- const [[inputElementId, inputElement], fileAsLocalTemp] = yield Promise.all([
1816
- (() => __awaiter(this, void 0, void 0, function* () {
1817
- const inputElementId = yield this._page.evaluate(() => WAPI.createTemporaryFileInput());
1818
- const inputElement = yield this._page.$(`#${inputElementId}`);
1819
- return [inputElementId, inputElement];
1820
- }))(),
1821
- (0, tools_1.assertFile)(file, filename, tools_1.FileOutputTypes.TEMP_FILE_PATH, requestConfig || {})
1822
- ]);
1823
- //@ts-ignore
1824
- yield inputElement.uploadFile(fileAsLocalTemp);
1825
- file = inputElementId;
1826
- /**
1827
- * Old method of asserting that the file be a data url - cons = time wasted serializing/deserializing large file to and from b64.
1828
- */
1829
- // file = await assertFile(file, filename, FileOutputTypes.DATA_URL as any,requestConfig || {}) as string
1830
- const res = yield this.pup(({ to, file, filename, caption, quotedMsgId, waitForId, ptt, withoutPreview, hideTags, viewOnce }) => WAPI.sendImage(file, to, filename, caption, quotedMsgId, waitForId, ptt, withoutPreview, hideTags, viewOnce), { to, file, filename, caption, quotedMsgId, waitForId, ptt, withoutPreview, hideTags, viewOnce });
1831
- if (fileAsLocalTemp)
1832
- yield (0, tools_1.rmFileAsync)(fileAsLocalTemp);
1833
- if (err.includes(res))
1834
- console.error(res);
1835
- return (err.includes(res) ? false : res);
1836
- });
1837
- }
1838
- /**
1839
- * Automatically sends a youtube link with the auto generated link preview. You can also add a custom message.
1840
- * @param chatId
1841
- * @param url string A youtube link.
1842
- * @param text string Custom text as body of the message, this needs to include the link or it will be appended after the link.
1843
- * @param thumbnail string Base64 of the jpeg/png which will be used to override the automatically generated thumbnail.
1844
- * @param quotedMsgId [INSIDERS] Send this link preview message in response to a given quoted message
1845
- * @param customSize [INSIDERS] Anchor the size of the thumbnail
1846
- */
1847
- sendYoutubeLink(to, url, text = '', thumbnail, quotedMsgId, customSize) {
1848
- return __awaiter(this, void 0, void 0, function* () {
1849
- return this.sendLinkWithAutoPreview(to, url, text, thumbnail, quotedMsgId, customSize);
1850
- });
1851
- }
1852
- /**
1853
- * Automatically sends a link with the auto generated link preview. You can also add a custom message.
1854
- * @param chatId
1855
- * @param url string A link.
1856
- * @param text string Custom text as body of the message, this needs to include the link or it will be appended after the link.
1857
- * @param thumbnail Base64 of the jpeg/png which will be used to override the automatically generated thumbnail.
1858
- * @param quotedMsgId [INSIDERS] Send this link preview message in response to a given quoted message
1859
- * @param customSize [INSIDERS] Anchor the size of the thumbnail
1860
- */
1861
- sendLinkWithAutoPreview(to, url, text, thumbnail, quotedMsgId, customSize) {
1862
- var _a;
1863
- return __awaiter(this, void 0, void 0, function* () {
1864
- let linkData;
1865
- let thumb;
1866
- try {
1867
- linkData = (yield axios_1.default.get(`${((_a = this._createConfig) === null || _a === void 0 ? void 0 : _a.linkParser) || "https://link.openwa.cloud/api"}?url=${url}`)).data;
1868
- logging_1.log.info("Got link data");
1869
- if (!thumbnail)
1870
- thumb = yield (0, tools_1.getDUrl)(linkData.image);
1871
- }
1872
- catch (error) {
1873
- console.error(error);
1874
- }
1875
- if (linkData && (thumbnail || thumb))
1876
- return yield this.sendMessageWithThumb(thumbnail || thumb, url, linkData.title, linkData.description, text, to, quotedMsgId, customSize);
1877
- else
1878
- return yield this.pup(({ to, url, text, thumbnail }) => WAPI.sendLinkWithAutoPreview(to, url, text, thumbnail), { to, url, text, thumbnail });
1879
- });
1880
- }
1881
- /**
1882
- *
1883
- * Sends a reply to a given message. Please note, you need to have at least sent one normal message to a contact in order for this to work properly.
1884
- *
1885
- * @param to string chatid
1886
- * @param content string reply text
1887
- * @param quotedMsgId string the msg id to reply to.
1888
- * @param sendSeen boolean If set to true, the chat will 'blue tick' all messages before sending the reply
1889
- * @returns `Promise<MessageId | false>` false if didn't work, otherwise returns message id.
1890
- */
1891
- reply(to, content, quotedMsgId, sendSeen) {
1892
- return __awaiter(this, void 0, void 0, function* () {
1893
- if (sendSeen)
1894
- yield this.sendSeen(to);
1895
- return yield this.pup(({ to, content, quotedMsgId }) => WAPI.reply(to, content, quotedMsgId), { to, content, quotedMsgId });
1896
- });
1897
- }
1898
- /**
1899
- * {@license:insiders@}
1900
- *
1901
- * Check if a recipient has read receipts on.
1902
- *
1903
- * This will only work if you have chats sent back and forth between you and the contact 1-1.
1904
- *
1905
- * @param contactId The Id of the contact with which you have an existing conversation with messages already.
1906
- * @returns `Promise<string | boolean>` true or false or a string with an explaintaion of why it wasn't able to determine the read receipts.
1907
- *
1908
- */
1909
- checkReadReceipts(contactId) {
1910
- return __awaiter(this, void 0, void 0, function* () {
1911
- return yield this.pup(({ contactId }) => WAPI.checkReadReceipts(contactId), { contactId });
1912
- });
1913
- }
1914
- /**
1915
- * Sends a file to given chat, with caption or not, using base64. This is exactly the same as sendImage
1916
- *
1917
- * Please note that any file that resolves to mime-type `octet-stream` will, by default, resolve to an MP4 file.
1918
- *
1919
- * If you want a specific filetype, then explcitly select the correct mime-type from https://www.iana.org/assignments/media-types/media-types.xhtml
1920
- *
1921
- *
1922
- * @param to chat id `xxxxx@c.us`
1923
- * @param file DataURL data:image/xxx;base64,xxx or the RELATIVE (should start with `./` or `../`) path of the file you want to send. With the latest version, you can now set this to a normal URL (for example [GET] `https://file-examples-com.github.io/uploads/2017/10/file_example_JPG_2500kB.jpg`).
1924
- * @param filename string xxxxx
1925
- * @param caption string xxxxx With an [INSIDERS LICENSE-KEY](https://gum.co/open-wa?tier=Insiders%20Program) you can also tag people in groups with `@[number]`. For example if you want to mention the user with the number `44771234567`, just add `@44771234567` in the caption.
1926
- * @param quotedMsgId string true_0000000000@c.us_JHB2HB23HJ4B234HJB to send as a reply to a message
1927
- * @param waitForId boolean default: false set this to true if you want to wait for the id of the message. By default this is set to false as it will take a few seconds to retrieve to the key of the message and this waiting may not be desirable for the majority of users.
1928
- * @param ptt boolean default: false set this to true if you want to send the file as a push to talk file.
1929
- * @param withoutPreview boolean default: false set this to true if you want to send the file without a preview (i.e as a file). This is useful for preventing auto downloads on recipient devices.
1930
- * @param hideTags boolean default: false [INSIDERS] set this to try silent tag someone in the caption
1931
- * @returns `Promise <boolean | MessageId>` This will either return true or the id of the message. It will return true after 10 seconds even if waitForId is true
1932
- */
1933
- sendFile(to, file, filename, caption, quotedMsgId, waitForId, ptt, withoutPreview, hideTags, viewOnce, requestConfig) {
1934
- return __awaiter(this, void 0, void 0, function* () {
1935
- return this.sendImage(to, file, filename, caption, quotedMsgId, waitForId, ptt, withoutPreview, hideTags, viewOnce, requestConfig);
1936
- });
1937
- }
1938
- /**
1939
- * {@license:insiders@}
1940
- *
1941
- * Checks whether or not the group id provided is known to be unsafe by the contributors of the library.
1942
- * @param groupChatId The group chat you want to deteremine is unsafe
1943
- * @returns `Promise <boolean | string>` This will either return a boolean indiciating whether this group chat id is considered unsafe or an error message as a string
1944
- */
1945
- isGroupIdUnsafe(groupChatId) {
1946
- return __awaiter(this, void 0, void 0, function* () {
1947
- const { data } = yield axios_1.default.post('https://openwa.dev/groupId-check', {
1948
- groupChatId,
1949
- sessionInfo: this.getSessionInfo(),
1950
- config: this.getConfig()
1951
- });
1952
- if (data.unsafe)
1953
- console.warn(`${groupChatId} is marked as unsafe`);
1954
- return data.err || data.unsafe;
1955
- });
1956
- }
1957
- /**
1958
- * Attempts to send a file as a voice note. Useful if you want to send an mp3 file.
1959
- * @param to chat id `xxxxx@c.us`
1960
- * @param file base64 data:image/xxx;base64,xxx or the path of the file you want to send.
1961
- * @param quotedMsgId string true_0000000000@c.us_JHB2HB23HJ4B234HJB to send as a reply to a message
1962
- * @returns `Promise <boolean | string>` This will either return true or the id of the message. It will return true after 10 seconds even if waitForId is true
1963
- */
1964
- sendPtt(to, file, quotedMsgId) {
1965
- return __awaiter(this, void 0, void 0, function* () {
1966
- return this.sendImage(to, file, 'ptt.ogg', '', quotedMsgId ? quotedMsgId : null, true, true);
1967
- });
1968
- }
1969
- /**
1970
- * Send an audio file with the default audio player (not PTT/voice message)
1971
- * @param to chat id `xxxxx@c.us`
1972
- * @param base64 base64 data:image/xxx;base64,xxx or the path of the file you want to send.
1973
- * @param quotedMsgId string true_0000000000@c.us_JHB2HB23HJ4B234HJB to send as a reply to a message
1974
- */
1975
- sendAudio(to, file, quotedMsgId) {
1976
- return __awaiter(this, void 0, void 0, function* () {
1977
- return this.sendFile(to, file, 'file.mp3', '', quotedMsgId, true, false, false, false);
1978
- });
1979
- }
1980
- /**
1981
- * Send a poll to a group chat
1982
- * @param to chat id - a group chat is required
1983
- * @param name the name of the poll
1984
- * @param options an array of poll options
1985
- * @param quotedMsgId A message to quote when sending the poll
1986
- * @param allowMultiSelect Whether or not to allow multiple selections. default false
1987
- */
1988
- sendPoll(to, name, options, quotedMsgId, allowMultiSelect) {
1989
- return __awaiter(this, void 0, void 0, function* () {
1990
- return yield this.pup(({ to, name, options, quotedMsgId, allowMultiSelect }) => {
1991
- return WAPI.sendPoll(to, name, options, quotedMsgId, allowMultiSelect);
1992
- }, { to, name, options, quotedMsgId, allowMultiSelect });
1993
- });
1994
- }
1995
- /**
1996
- * Sends a video to given chat as a gif, with caption or not, using base64
1997
- * @param to chat id `xxxxx@c.us`
1998
- * @param file DataURL data:image/xxx;base64,xxx or the RELATIVE (should start with `./` or `../`) path of the file you want to send. With the latest version, you can now set this to a normal URL (for example [GET] `https://file-examples-com.github.io/uploads/2017/10/file_example_JPG_2500kB.jpg`).
1999
- * @param filename string xxxxx
2000
- * @param caption string xxxxx
2001
- * @param quotedMsgId string true_0000000000@c.us_JHB2HB23HJ4B234HJB to send as a reply to a message
2002
- * @param requestConfig {} By default the request is a get request, however you can override that and many other options by sending this parameter. You can read more about this parameter here: https://github.com/axios/axios#request-config
2003
- */
2004
- sendVideoAsGif(to, file, filename, caption, quotedMsgId, requestConfig = {}) {
2005
- return __awaiter(this, void 0, void 0, function* () {
2006
- //check if the 'base64' file exists
2007
- if (!(0, tools_1.isDataURL)(file)) {
2008
- //must be a file then
2009
- const relativePath = path.join(path.resolve(process.cwd(), file || ''));
2010
- if (fs.existsSync(file) || fs.existsSync(relativePath)) {
2011
- file = yield (0, datauri_1.default)(fs.existsSync(file) ? file : relativePath);
2012
- }
2013
- else if ((0, is_url_superb_1.default)(file)) {
2014
- file = yield (0, tools_1.getDUrl)(file, requestConfig);
2015
- }
2016
- else
2017
- throw new errors_1.CustomError(errors_1.ERROR_NAME.FILE_NOT_FOUND, 'Cannot find file. Make sure the file reference is relative, a valid URL or a valid DataURL');
2018
- }
2019
- return yield this.pup(({ to, file, filename, caption, quotedMsgId }) => {
2020
- return WAPI.sendVideoAsGif(file, to, filename, caption, quotedMsgId);
2021
- }, { to, file, filename, caption, quotedMsgId });
2022
- });
2023
- }
2024
- /**
2025
- * Sends a video to given chat as a gif by using a giphy link, with caption or not, using base64
2026
- * @param to chat id `xxxxx@c.us`
2027
- * @param giphyMediaUrl string https://media.giphy.com/media/oYtVHSxngR3lC/giphy.gif => https://i.giphy.com/media/oYtVHSxngR3lC/200w.mp4
2028
- * @param caption string xxxxx
2029
- */
2030
- sendGiphy(to, giphyMediaUrl, caption) {
2031
- return __awaiter(this, void 0, void 0, function* () {
2032
- const ue = /^https?:\/\/media\.giphy\.com\/media\/([a-zA-Z0-9]+)/;
2033
- const n = ue.exec(giphyMediaUrl);
2034
- if (n) {
2035
- const r = `https://i.giphy.com/${n[1]}.mp4`;
2036
- const filename = `${n[1]}.mp4`;
2037
- const dUrl = yield (0, tools_1.getDUrl)(r);
2038
- return yield this.pup(({ to, dUrl, filename, caption }) => {
2039
- WAPI.sendVideoAsGif(dUrl, to, filename, caption);
2040
- }, { to, dUrl, filename, caption });
2041
- }
2042
- else {
2043
- console.log('something is wrong with this giphy link');
2044
- logging_1.log.error('something is wrong with this giphy link', giphyMediaUrl);
2045
- return;
2046
- }
2047
- });
2048
- }
2049
- /**
2050
- * Sends a file by Url or custom options
2051
- * @param to chat id `xxxxx@c.us`
2052
- * @param url string https://i.giphy.com/media/oYtVHSxngR3lC/200w.mp4
2053
- * @param filename string 'video.mp4'
2054
- * @param caption string xxxxx
2055
- * @param quotedMsgId string true_0000000000@c.us_JHB2HB23HJ4B234HJB to send as a reply to a message
2056
- * @param requestConfig {} By default the request is a get request, however you can override that and many other options by sending this parameter. You can read more about this parameter here: https://github.com/axios/axios#request-config
2057
- * @param waitForId boolean default: false set this to true if you want to wait for the id of the message. By default this is set to false as it will take a few seconds to retrieve to the key of the message and this waiting may not be desirable for the majority of users.
2058
- * @param ptt boolean default: false set this to true if you want to send the file as a push to talk file.
2059
- * @param withoutPreview boolean default: false set this to true if you want to send the file without a preview (i.e as a file). This is useful for preventing auto downloads on recipient devices.
2060
- */
2061
- sendFileFromUrl(to, url, filename, caption, quotedMsgId, requestConfig = {}, waitForId, ptt, withoutPreview, hideTags, viewOnce) {
2062
- return __awaiter(this, void 0, void 0, function* () {
2063
- return yield this.sendFile(to, url, filename, caption, quotedMsgId, waitForId, ptt, withoutPreview, hideTags, viewOnce, requestConfig);
2064
- });
2065
- }
2066
- /**
2067
- * Returns an object with all of your host device details
2068
- */
2069
- getMe() {
2070
- return __awaiter(this, void 0, void 0, function* () {
2071
- return yield this._page.evaluate(() => WAPI.getMe());
2072
- });
2073
- }
2074
- /**
2075
- * Returns an object with properties of internal features and boolean values that represent if the respective feature is enabled or not.
2076
- */
2077
- getFeatures() {
2078
- return __awaiter(this, void 0, void 0, function* () {
2079
- return yield this._page.evaluate(() => WAPI.getFeatures());
2080
- });
2081
- }
2082
- /**
2083
- * Returns a PNG DataURL screenshot of the session
2084
- * @param chatId Chat ID to open before taking a snapshot
2085
- * @param width Width of the viewport for the snapshot. Height also required if you want to resize.
2086
- * @param height Height of the viewport for the snapshot. Width also required if you want to resize.
2087
- * @returns `Promise<DataURL>`
2088
- */
2089
- getSnapshot(chatId, width, height) {
2090
- return __awaiter(this, void 0, void 0, function* () {
2091
- if (width && height)
2092
- yield this.resizePage(width, height);
2093
- const snapshotElement = chatId ? yield this._page.evaluateHandle(({ chatId }) => WAPI.getSnapshotElement(chatId), { chatId }) : this.getPage();
2094
- const screenshot = yield snapshotElement.screenshot({
2095
- type: "png",
2096
- encoding: "base64"
2097
- });
2098
- return `data:image/png;base64,${screenshot}`;
2099
- });
2100
- }
2101
- /**
2102
- * Returns some metrics of the session/page.
2103
- * @returns `Promise<any>`
2104
- */
2105
- metrics() {
2106
- return __awaiter(this, void 0, void 0, function* () {
2107
- const metrics = yield this._page.metrics();
2108
- const sessionMetrics = yield this.pup(() => WAPI.launchMetrics());
2109
- const res = Object.assign(Object.assign({}, (metrics || {})), (sessionMetrics || {}));
2110
- logging_1.log.info("Metrics:", res);
2111
- return res;
2112
- });
2113
- }
2114
- /**
2115
- * Returns an array of group ids where the host account is admin
2116
- */
2117
- iAmAdmin() {
2118
- return __awaiter(this, void 0, void 0, function* () {
2119
- return yield this.pup(() => WAPI.iAmAdmin());
2120
- });
2121
- }
2122
- /**
2123
- * Returns an array of group ids where the host account has been kicked
2124
- */
2125
- getKickedGroups() {
2126
- return __awaiter(this, void 0, void 0, function* () {
2127
- return yield this.pup(() => WAPI.getKickedGroups());
2128
- });
2129
- }
2130
- /**
2131
- * Syncs contacts with phone. This promise does not resolve so it will instantly return true.
2132
- */
2133
- syncContacts() {
2134
- return __awaiter(this, void 0, void 0, function* () {
2135
- //@ts-ignore
2136
- return yield this.pup(() => WAPI.syncContacts());
2137
- });
2138
- }
2139
- /**
2140
- * Easily get the amount of messages loaded up in the session. This will allow you to determine when to clear chats/cache.
2141
- */
2142
- getAmountOfLoadedMessages() {
2143
- return __awaiter(this, void 0, void 0, function* () {
2144
- return yield this.pup(() => WAPI.getAmountOfLoadedMessages());
2145
- });
2146
- }
2147
- /**
2148
- * Find any product listings of the given number. Use this to query a catalog
2149
- *
2150
- * @param id id of business profile (i.e the number with @c.us)
2151
- * @returns None
2152
- */
2153
- getBusinessProfilesProducts(id) {
2154
- return __awaiter(this, void 0, void 0, function* () {
2155
- return yield this.pup(({ id }) => WAPI.getBusinessProfilesProducts(id), { id });
2156
- });
2157
- }
2158
- /**
2159
- * Get the business info of a given contact id
2160
- *
2161
- * @param id id of business profile (i.e the number with @c.us)
2162
- * @returns None
2163
- */
2164
- getBusinessProfile(id) {
2165
- return __awaiter(this, void 0, void 0, function* () {
2166
- return yield this.pup(({ id }) => WAPI.getBusinessProfile(id), { id });
2167
- });
2168
- }
2169
- /**
2170
- * Sends product with image to chat
2171
- * @param imgBase64 Base64 image data
2172
- * @param chatid string the id of the chat that you want to send this product to
2173
- * @param caption string the caption you want to add to this message
2174
- * @param bizNumber string the @c.us number of the business account from which you want to grab the product
2175
- * @param productId string the id of the product within the main catalog of the aforementioned business
2176
- * @returns
2177
- */
2178
- sendImageWithProduct(to, image, caption, bizNumber, productId) {
2179
- return __awaiter(this, void 0, void 0, function* () {
2180
- return yield this.pup(({ to, image, bizNumber, caption, productId }) => {
2181
- WAPI.sendImageWithProduct(image, to, caption, bizNumber, productId);
2182
- }, { to, image, bizNumber, caption, productId });
2183
- });
2184
- }
2185
- /**
2186
- * @deprecated
2187
- * Feature Currently only available with Premium License accounts.
2188
- *
2189
- * Send a custom product to a chat. Please see [[CustomProduct]] for details.
2190
- *
2191
- * Caveats:
2192
- * - URL will not work (unable to click), you will have to send another message with the URL.
2193
- * - Recipient will see a thin banner under picture that says "Something went wrong"
2194
- * - This will only work if you have at least 1 product already in your catalog
2195
- * - Only works on Business accounts
2196
- */
2197
- sendCustomProduct(to, image, productData) {
2198
- return __awaiter(this, void 0, void 0, function* () {
2199
- return yield this.pup(({ to, image, productData }) => WAPI.sendCustomProduct(to, image, productData), { to, image, productData });
2200
- });
2201
- }
2202
- /**
2203
- * Sends contact card to given chat id. You can use this to send multiple contacts but they will show up as multiple single-contact messages.
2204
- * @param {string} to 'xxxx@c.us'
2205
- * @param {string|array} contact 'xxxx@c.us' | ['xxxx@c.us', 'yyyy@c.us', ...]
2206
- */
2207
- sendContact(to, contactId) {
2208
- return __awaiter(this, void 0, void 0, function* () {
2209
- return yield this.pup(({ to, contactId }) => WAPI.sendContact(to, contactId), { to, contactId });
2210
- });
2211
- }
2212
- /**
2213
- *
2214
- * {@license:insiders@}
2215
- *
2216
- * Sends multiple contacts as a single message
2217
- *
2218
- * @param to 'xxxx@c.us'
2219
- * @param contact ['xxxx@c.us', 'yyyy@c.us', ...]
2220
- */
2221
- sendMultipleContacts(to, contactIds) {
2222
- return __awaiter(this, void 0, void 0, function* () {
2223
- return yield this.pup(({ to, contactIds }) => WAPI.sendMultipleContacts(to, contactIds), { to, contactIds });
2224
- });
2225
- }
2226
- /**
2227
- * Simulate '...typing' in chat
2228
- * @param {string} to 'xxxx@c.us'
2229
- * @param {boolean} on turn on similated typing, false to turn it off you need to manually turn this off.
2230
- */
2231
- simulateTyping(to, on) {
2232
- return __awaiter(this, void 0, void 0, function* () {
2233
- return yield this.pup(({ to, on }) => WAPI.simulateTyping(to, on), { to, on });
2234
- });
2235
- }
2236
- /**
2237
- * Simulate '...recording' in chat
2238
- * @param {string} to 'xxxx@c.us'
2239
- * @param {boolean} on turn on similated recording, false to turn it off you need to manually turn this off.
2240
- */
2241
- simulateRecording(to, on) {
2242
- return __awaiter(this, void 0, void 0, function* () {
2243
- return yield this.pup(({ to, on }) => WAPI.simulateRecording(to, on), { to, on });
2244
- });
2245
- }
2246
- /**
2247
- * @param id The id of the conversation
2248
- * @param archive boolean true => archive, false => unarchive
2249
- * @return boolean true: worked, false: didnt work (probably already in desired state)
2250
- */
2251
- archiveChat(id, archive) {
2252
- return __awaiter(this, void 0, void 0, function* () {
2253
- return yield this.pup(({ id, archive }) => WAPI.archiveChat(id, archive), { id, archive });
2254
- });
2255
- }
2256
- /**
2257
- * Pin/Unpin chats
2258
- *
2259
- * @param id The id of the conversation
2260
- * @param pin boolean true => pin, false => unpin
2261
- * @return boolean true: worked
2262
- */
2263
- pinChat(id, pin) {
2264
- return __awaiter(this, void 0, void 0, function* () {
2265
- return yield this.pup(({ id, pin }) => WAPI.pinChat(id, pin), { id, pin });
2266
- });
2267
- }
2268
- /**
2269
- * Pin/Unpin message
2270
- *
2271
- * @param id The id of the message
2272
- * @param pin boolean true => pin, false => unpin
2273
- * @param pinDuration The length of time to pin the message. Default `ThirtyDays`
2274
- * @return boolean true: worked
2275
- */
2276
- pinMessage(id, pin, pinDuration = "ThirtyDays") {
2277
- return __awaiter(this, void 0, void 0, function* () {
2278
- return yield this.pup(({ id, pin, pinDuration }) => WAPI.pinMessage(id, pin, pinDuration), { id, pin, pinDuration });
2279
- });
2280
- }
2281
- /**
2282
- * Keep a message inside an ephemeral chat
2283
- *
2284
- * @param id The id of the message
2285
- * @return boolean true: worked
2286
- */
2287
- keepMessage(id, keep) {
2288
- return __awaiter(this, void 0, void 0, function* () {
2289
- return yield this.pup(({ id, keep }) => WAPI.keepMessage(id, keep), { id, keep });
2290
- });
2291
- }
2292
- /**
2293
- *
2294
- * {@license:insiders@}
2295
- *
2296
- * Mutes a conversation for a given duration. If already muted, this will update the muted duration. Mute durations are relative from when the method is called.
2297
- * @param chatId The id of the conversation you want to mute
2298
- * @param muteDuration ChatMuteDuration enum of the time you want this chat to be muted for.
2299
- * @return boolean true: worked or error code or message
2300
- */
2301
- muteChat(chatId, muteDuration) {
2302
- return __awaiter(this, void 0, void 0, function* () {
2303
- return yield this.pup(({ chatId, muteDuration }) => WAPI.muteChat(chatId, muteDuration), { chatId, muteDuration });
2304
- });
2305
- }
2306
- /**
2307
- * Checks if a chat is muted
2308
- * @param chatId The id of the chat you want to check
2309
- * @returns boolean. `false` if the chat does not exist.
2310
- */
2311
- isChatMuted(chatId) {
2312
- return __awaiter(this, void 0, void 0, function* () {
2313
- return yield this.pup(({ chatId }) => WAPI.isChatMuted(chatId), { chatId });
2314
- });
2315
- }
2316
- /**
2317
- *
2318
- * {@license:insiders@}
2319
- *
2320
- * Unmutes a conversation.
2321
- * @param id The id of the conversation you want to mute
2322
- * @return boolean true: worked or error code or message
2323
- */
2324
- unmuteChat(chatId) {
2325
- return __awaiter(this, void 0, void 0, function* () {
2326
- return yield this.pup(({ chatId }) => WAPI.unmuteChat(chatId), { chatId });
2327
- });
2328
- }
2329
- /**
2330
- * Forward an array of messages to a specific chat using the message ids or Objects
2331
- *
2332
- * @param to '000000000000@c.us'
2333
- * @param messages this can be any mixture of message ids or message objects
2334
- * @param skipMyMessages This indicates whether or not to skip your own messages from the array
2335
- */
2336
- forwardMessages(to, messages, skipMyMessages) {
2337
- return __awaiter(this, void 0, void 0, function* () {
2338
- return yield this.pup(({ to, messages, skipMyMessages }) => WAPI.forwardMessages(to, messages, skipMyMessages), { to, messages, skipMyMessages });
2339
- });
2340
- }
2341
- /**
2342
- * Ghost forwarding is like a normal forward but as if it were sent from the host phone [i.e it doesn't show up as forwarded.]
2343
- * Any potential abuse of this method will see it become paywalled.
2344
- * @param to: Chat id to forward the message to
2345
- * @param messageId: message id of the message to forward. Please note that if it is not loaded, this will return false - even if it exists.
2346
- * @returns `Promise<MessageId | boolean>`
2347
- */
2348
- ghostForward(to, messageId) {
2349
- return __awaiter(this, void 0, void 0, function* () {
2350
- return yield this.pup(({ to, messageId }) => WAPI.ghostForward(to, messageId), { to, messageId });
2351
- });
2352
- }
2353
- /**
2354
- * Retrieves all contacts
2355
- * @returns array of [Contact]
2356
- */
2357
- getAllContacts() {
2358
- return __awaiter(this, void 0, void 0, function* () {
2359
- return yield this.pup(() => WAPI.getAllContacts());
2360
- });
2361
- }
2362
- getWAVersion() {
2363
- return __awaiter(this, void 0, void 0, function* () {
2364
- return yield this.pup(() => WAPI.getWAVersion());
2365
- });
2366
- }
2367
- /**
2368
- * Generate a pre-filled github issue link to easily report a bug
2369
- */
2370
- getIssueLink() {
2371
- return __awaiter(this, void 0, void 0, function* () {
2372
- return (0, tools_1.generateGHIssueLink)(this.getConfig(), this.getSessionInfo());
2373
- });
2374
- }
2375
- /**
2376
- * Retrieves if the phone is online. Please note that this may not be real time.
2377
- * @returns Boolean
2378
- */
2379
- isConnected() {
2380
- return __awaiter(this, void 0, void 0, function* () {
2381
- return yield this.pup(() => WAPI.isConnected());
2382
- });
2383
- }
2384
- /**
2385
- * Logs out from the session.
2386
- * @param preserveSessionData skip session.data.json file invalidation
2387
- * Please be careful when using this as it can exit the whole process depending on your config
2388
- */
2389
- logout(preserveSessionData = false) {
2390
- return __awaiter(this, void 0, void 0, function* () {
2391
- if (!preserveSessionData) {
2392
- logging_1.log.info(`LOGOUT CALLED. INVALIDATING SESSION DATA`);
2393
- yield (0, browser_1.invalidateSesssionData)(this._createConfig);
2394
- }
2395
- return yield this.pup(() => WAPI.logout());
2396
- });
2397
- }
2398
- /**
2399
- * @deprecated No longer works due to multi-device changes
2400
- * Retrieves Battery Level
2401
- * @returns Number
2402
- */
2403
- getBatteryLevel() {
2404
- return __awaiter(this, void 0, void 0, function* () {
2405
- return yield this.pup(() => WAPI.getBatteryLevel());
2406
- });
2407
- }
2408
- /**
2409
- * Retrieves whether or not phone is plugged in (i.e on charge)
2410
- * @returns Number
2411
- */
2412
- getIsPlugged() {
2413
- return __awaiter(this, void 0, void 0, function* () {
2414
- return yield this.pup(() => WAPI.getIsPlugged());
2415
- });
2416
- }
2417
- /**
2418
- * Retrieves the host device number. Use this number when registering for a license key
2419
- * @returns Number
2420
- */
2421
- getHostNumber() {
2422
- return __awaiter(this, void 0, void 0, function* () {
2423
- if (!this._hostAccountNumber)
2424
- this._hostAccountNumber = (yield this.pup(() => WAPI.getHostNumber()));
2425
- return this._hostAccountNumber;
2426
- });
2427
- }
2428
- /**
2429
- * Returns the the type of license key used by the session.
2430
- * @returns
2431
- */
2432
- getLicenseType() {
2433
- return __awaiter(this, void 0, void 0, function* () {
2434
- return yield this.pup(() => WAPI.getLicenseType());
2435
- });
2436
- }
2437
- /**
2438
- * The EASY API uses this string to secure a subdomain on the openwa public tunnel service.
2439
- * @returns
2440
- */
2441
- getTunnelCode() {
2442
- return __awaiter(this, void 0, void 0, function* () {
2443
- const sessionId = this.getSessionId();
2444
- return yield this.pup(sessionId => WAPI.getTunnelCode(sessionId), sessionId);
2445
- });
2446
- }
2447
- /**
2448
- * Get an array of chatIds with their respective last message's timestamp.
2449
- *
2450
- * This is useful for determining what chats are old/stale and need to be deleted.
2451
- */
2452
- getLastMsgTimestamps() {
2453
- return __awaiter(this, void 0, void 0, function* () {
2454
- return yield this.pup(() => WAPI.getLastMsgTimestamps());
2455
- });
2456
- }
2457
- /**
2458
- * Retrieves all chats
2459
- * @returns array of [Chat]
2460
- */
2461
- getAllChats(withNewMessageOnly = false) {
2462
- return __awaiter(this, void 0, void 0, function* () {
2463
- if (withNewMessageOnly) {
2464
- return yield this.pup(() => WAPI.getAllChatsWithNewMsg());
2465
- }
2466
- else {
2467
- return yield this.pup(() => WAPI.getAllChats());
2468
- }
2469
- });
2470
- }
2471
- /**
2472
- * retrieves all Chat Ids
2473
- * @returns array of [ChatId]
2474
- */
2475
- getAllChatIds() {
2476
- return __awaiter(this, void 0, void 0, function* () {
2477
- return yield this.pup(() => WAPI.getAllChatIds());
2478
- });
2479
- }
2480
- /**
2481
- * retrieves an array of IDs of accounts blocked by the host account.
2482
- * @returns `Promise<ChatId[]>`
2483
- */
2484
- getBlockedIds() {
2485
- return __awaiter(this, void 0, void 0, function* () {
2486
- return yield this.pup(() => WAPI.getBlockedIds());
2487
- });
2488
- }
2489
- /**
2490
- * @deprecated
2491
- *
2492
- * Retrieves all chats with messages
2493
- *
2494
- * Please use `getAllUnreadMessages` instead of this to see all messages indicated by the green dots in the chat.
2495
- *
2496
- * @returns array of [Chat]
2497
- */
2498
- getAllChatsWithMessages(withNewMessageOnly = false) {
2499
- return __awaiter(this, void 0, void 0, function* () {
2500
- return JSON.parse(yield this.pup(withNewMessageOnly => WAPI.getAllChatsWithMessages(withNewMessageOnly), withNewMessageOnly));
2501
- });
2502
- }
2503
- /**
2504
- * Returns a properly formatted array of messages from to send to the openai api
2505
- *
2506
- * @param last The amount of previous messages to retrieve. Defaults to 10
2507
- * @returns
2508
- */
2509
- getGptArray(chatId, last = 10) {
2510
- return __awaiter(this, void 0, void 0, function* () {
2511
- return yield this.pup(({ chatId, last }) => WAPI.getGptArray(chatId, last), { chatId, last });
2512
- });
2513
- }
2514
- /**
2515
- * Retrieve all groups
2516
- * @returns array of groups
2517
- */
2518
- getAllGroups(withNewMessagesOnly = false) {
2519
- return __awaiter(this, void 0, void 0, function* () {
2520
- return yield this.pup((withNewMessagesOnly) => WAPI.getAllGroups(withNewMessagesOnly), withNewMessagesOnly);
2521
- });
2522
- }
2523
- /**
2524
- * Retrieve all commmunity Ids
2525
- * @returns array of group ids
2526
- */
2527
- getAllCommunities() {
2528
- return __awaiter(this, void 0, void 0, function* () {
2529
- return yield this.pup(() => WAPI.getCommunities());
2530
- });
2531
- }
2532
- /**
2533
- * Retrieves group members as [Id] objects
2534
- * @param groupId group id
2535
- */
2536
- getGroupMembersId(groupId) {
2537
- return __awaiter(this, void 0, void 0, function* () {
2538
- return yield this.pup(groupId => WAPI.getGroupParticipantIDs(groupId), groupId);
2539
- });
2540
- }
2541
- /**
2542
- * Returns the title and description of a given group id.
2543
- * @param groupId group id
2544
- */
2545
- getGroupInfo(groupId) {
2546
- return __awaiter(this, void 0, void 0, function* () {
2547
- return yield this.pup(groupId => WAPI.getGroupInfo(groupId), groupId);
2548
- });
2549
- }
2550
- /**
2551
- * Returns the community metadata. Like group metadata but with a `subGroups` property which is the group metadata of the community subgroups.
2552
- * @param communityId community id
2553
- */
2554
- getCommunityInfo(communityId) {
2555
- return __awaiter(this, void 0, void 0, function* () {
2556
- return yield this.pup(communityId => WAPI.getCommunityInfo(communityId), communityId);
2557
- });
2558
- }
2559
- /**
2560
- *
2561
- * Accepts a request from a recipient to join a group. Takes the message ID of the request message.
2562
- *
2563
- * @param {string} messageId
2564
- */
2565
- acceptGroupJoinRequest(messageId) {
2566
- return __awaiter(this, void 0, void 0, function* () {
2567
- return yield this.pup(messageId => WAPI.acceptGroupJoinRequest(messageId), messageId);
2568
- });
2569
- }
2570
- /**
2571
- * Retrieves community members Ids
2572
- * @param communityId community id
2573
- */
2574
- getCommunityParticipantIds(communityId) {
2575
- return __awaiter(this, void 0, void 0, function* () {
2576
- return yield this.pup(communityId => WAPI.getCommunityParticipantIds(communityId), communityId);
2577
- });
2578
- }
2579
- /**
2580
- * Retrieves community admin Ids
2581
- * @param communityId community id
2582
- */
2583
- getCommunityAdminIds(communityId) {
2584
- return __awaiter(this, void 0, void 0, function* () {
2585
- return yield this.pup(communityId => WAPI.getCommunityAdminIds(communityId), communityId);
2586
- });
2587
- }
2588
- /**
2589
- * Retrieves community members as Contact objects
2590
- * @param communityId community id
2591
- */
2592
- getCommunityParticipants(communityId) {
2593
- return __awaiter(this, void 0, void 0, function* () {
2594
- return yield this.pup(communityId => WAPI.getCommunityParticipants(communityId), communityId);
2595
- });
2596
- }
2597
- /**
2598
- * Retrieves community admins as Contact objects
2599
- * @param communityId community id
2600
- */
2601
- getCommunityAdmins(communityId) {
2602
- return __awaiter(this, void 0, void 0, function* () {
2603
- return yield this.pup(communityId => WAPI.getCommunityAdmins(communityId), communityId);
2604
- });
2605
- }
2606
- /** Joins a group via the invite link, code, or message
2607
- * @param link This param is the string which includes the invite link or code. The following work:
2608
- * - Follow this link to join my WA group: https://chat.whatsapp.com/DHTGJUfFJAV9MxOpZO1fBZ
2609
- * - https://chat.whatsapp.com/DHTGJUfFJAV9MxOpZO1fBZ
2610
- * - DHTGJUfFJAV9MxOpZO1fBZ
2611
- *
2612
- * If you have been removed from the group previously, it will return `401`
2613
- *
2614
- * @param returnChatObj boolean When this is set to true and if the group was joined successfully, it will return a serialzed Chat object which includes group information and metadata. This is useful when you want to immediately do something with group metadata.
2615
- *
2616
- *
2617
- * @returns `Promise<string | boolean | number>` Either false if it didn't work, or the group id.
2618
- */
2619
- joinGroupViaLink(link, returnChatObj) {
2620
- return __awaiter(this, void 0, void 0, function* () {
2621
- return yield this.pup(({ link, returnChatObj }) => WAPI.joinGroupViaLink(link, returnChatObj), { link, returnChatObj });
2622
- });
2623
- }
2624
- /**
2625
- * Block contact
2626
- * @param {string} id '000000000000@c.us'
2627
- */
2628
- contactBlock(id) {
2629
- return __awaiter(this, void 0, void 0, function* () {
2630
- return yield this.pup(id => WAPI.contactBlock(id), id);
2631
- });
2632
- }
2633
- /**
2634
- * {@license:restricted@}
2635
- *
2636
- * Report a contact for spam, block them and attempt to clear chat.
2637
- *
2638
- * @param {string} id '000000000000@c.us'
2639
- */
2640
- reportSpam(id) {
2641
- return __awaiter(this, void 0, void 0, function* () {
2642
- return yield this.pup(id => WAPI.REPORTSPAM(id), id);
2643
- });
2644
- }
2645
- /**
2646
- * Unblock contact
2647
- * @param {string} id '000000000000@c.us'
2648
- */
2649
- contactUnblock(id) {
2650
- return __awaiter(this, void 0, void 0, function* () {
2651
- return yield this.pup(id => WAPI.contactUnblock(id), id);
2652
- });
2653
- }
2654
- /**
2655
- * Removes the host device from the group
2656
- * @param groupId group id
2657
- */
2658
- leaveGroup(groupId) {
2659
- return __awaiter(this, void 0, void 0, function* () {
2660
- return yield this.pup(groupId => WAPI.leaveGroup(groupId), groupId);
2661
- });
2662
- }
2663
- /**
2664
- * Extracts vcards from a message.This works on messages of typ `vcard` or `multi_vcard`
2665
- * @param msgId string id of the message to extract the vcards from
2666
- * @returns [vcard]
2667
- * ```
2668
- * [
2669
- * {
2670
- * displayName:"Contact name",
2671
- * vcard: "loong vcard string"
2672
- * }
2673
- * ]
2674
- * ```
2675
- * or false if no valid vcards found.
2676
- *
2677
- * Please use [vcf](https://www.npmjs.com/package/vcf) to convert a vcard string into a json object
2678
- */
2679
- getVCards(msgId) {
2680
- return __awaiter(this, void 0, void 0, function* () {
2681
- return yield this.pup(msgId => WAPI.getVCards(msgId), msgId);
2682
- });
2683
- }
2684
- /**
2685
- * Returns group members [Contact] objects
2686
- * @param groupId
2687
- */
2688
- getGroupMembers(groupId) {
2689
- return __awaiter(this, void 0, void 0, function* () {
2690
- const membersIds = yield this.getGroupMembersId(groupId);
2691
- logging_1.log.info("group members ids", membersIds);
2692
- if (!Array.isArray(membersIds)) {
2693
- console.error("group members ids is not an array", membersIds);
2694
- return [];
2695
- }
2696
- const actions = membersIds.map(memberId => {
2697
- return this.getContact(memberId);
2698
- });
2699
- return yield Promise.all(actions);
2700
- });
2701
- }
2702
- /**
2703
- * Retrieves contact detail object of given contact id
2704
- * @param contactId
2705
- * @returns contact detial as promise
2706
- */
2707
- //@ts-ignore
2708
- getContact(contactId) {
2709
- return __awaiter(this, void 0, void 0, function* () {
2710
- return yield this.pup(contactId => WAPI.getContact(contactId), contactId);
2711
- });
2712
- }
2713
- /**
2714
- * Retrieves chat object of given contact id
2715
- * @param contactId
2716
- * @returns contact detial as promise
2717
- */
2718
- getChatById(contactId) {
2719
- return __awaiter(this, void 0, void 0, function* () {
2720
- return yield this.pup(contactId => WAPI.getChatById(contactId), contactId);
2721
- });
2722
- }
2723
- /**
2724
- * Retrieves message object of given message id
2725
- * @param messageId
2726
- * @returns message object
2727
- */
2728
- getMessageById(messageId) {
2729
- return __awaiter(this, void 0, void 0, function* () {
2730
- return yield this.pup(messageId => WAPI.getMessageById(messageId), messageId);
2731
- });
2732
- }
2733
- /**
2734
- * {@license:insiders@}
2735
- *
2736
- * Get the detailed message info for a group message sent out by the host account.
2737
- * @param messageId The message Id
2738
- */
2739
- getMessageInfo(messageId) {
2740
- return __awaiter(this, void 0, void 0, function* () {
2741
- return yield this.pup(messageId => WAPI.getMessageInfo(messageId), messageId);
2742
- });
2743
- }
2744
- /**
2745
- * {@license:insiders@}
2746
- *
2747
- * Retrieves an order object
2748
- * @param messageId or OrderId
2749
- * @returns order object
2750
- */
2751
- getOrder(id) {
2752
- return __awaiter(this, void 0, void 0, function* () {
2753
- return yield this.pup(id => WAPI.getOrder(id), id);
2754
- });
2755
- }
2756
- /**
2757
- * {@license:insiders@}
2758
- *
2759
- * Add a product to your catalog
2760
- *
2761
- * @param {string} name The name of the product
2762
- * @param {number} price The price of the product
2763
- * @param {string} currency The 3-letter currenct code for the product
2764
- * @param {string[]} images An array of dataurl or base64 strings of product images, the first image will be used as the main image. At least one image is required.
2765
- * @param {string} description optional, the description of the product
2766
- * @param {string} url The url of the product for more information
2767
- * @param {string} internalId The internal/backoffice id of the product
2768
- * @param {boolean} isHidden Whether or not the product is shown publicly in your catalog
2769
- * @returns product object
2770
- */
2771
- createNewProduct(name, price, currency, images, description, url, internalId, isHidden) {
2772
- return __awaiter(this, void 0, void 0, function* () {
2773
- if (!Array.isArray(images))
2774
- images = [images];
2775
- images = yield Promise.all(images.map(image => (0, tools_1.ensureDUrl)(image)));
2776
- return yield this.pup(({ name, price, currency, images, description, url, internalId, isHidden }) => WAPI.createNewProduct(name, price, currency, images, description, url, internalId, isHidden), { name, price, currency, images, description, url, internalId, isHidden });
2777
- });
2778
- }
2779
- /**
2780
- * {@license:insiders@}
2781
- *
2782
- * Edit a product in your catalog
2783
- *
2784
- * @param {string} productId The catalog ID of the product
2785
- * @param {string} name The name of the product
2786
- * @param {number} price The price of the product
2787
- * @param {string} currency The 3-letter currenct code for the product
2788
- * @param {string[]} images An array of dataurl or base64 strings of product images, the first image will be used as the main image. At least one image is required.
2789
- * @param {string} description optional, the description of the product
2790
- * @param {string} url The url of the product for more information
2791
- * @param {string} internalId The internal/backoffice id of the product
2792
- * @param {boolean} isHidden Whether or not the product is shown publicly in your catalog
2793
- * @returns product object
2794
- */
2795
- editProduct(productId, name, price, currency, images, description, url, internalId, isHidden) {
2796
- return __awaiter(this, void 0, void 0, function* () {
2797
- return yield this.pup(({ productId, name, price, currency, images, description, url, internalId, isHidden }) => WAPI.editProduct(productId, name, price, currency, images, description, url, internalId, isHidden), { productId, name, price, currency, images, description, url, internalId, isHidden });
2798
- });
2799
- }
2800
- /**
2801
- * {@license:insiders@}
2802
- *
2803
- * Send a product to a chat
2804
- *
2805
- * @param {string} chatId The chatId
2806
- * @param {string} productId The id of the product
2807
- * @returns MessageID
2808
- */
2809
- sendProduct(chatId, productId) {
2810
- return __awaiter(this, void 0, void 0, function* () {
2811
- return yield this.pup(({ chatId, productId }) => WAPI.sendProduct(chatId, productId), { chatId, productId });
2812
- });
2813
- }
2814
- /**
2815
- *
2816
- * Remove a product from the host account's catalog
2817
- *
2818
- * @param {string} productId The id of the product
2819
- * @returns boolean
2820
- */
2821
- removeProduct(productId) {
2822
- return __awaiter(this, void 0, void 0, function* () {
2823
- return yield this.pup(({ productId }) => WAPI.removeProduct(productId), { productId });
2824
- });
2825
- }
2826
- /**
2827
- * Retrieves the last message sent by the host account in any given chat or globally.
2828
- * @param chatId This is optional. If no chat Id is set then the last message sent by the host account will be returned.
2829
- * @returns message object or `undefined` if the host account's last message could not be found.
2830
- */
2831
- getMyLastMessage(chatId) {
2832
- return __awaiter(this, void 0, void 0, function* () {
2833
- return yield this.pup(chatId => WAPI.getMyLastMessage(chatId), chatId);
2834
- });
2835
- }
2836
- /**
2837
- * Retrieves the starred messages in a given chat
2838
- * @param chatId Chat ID to filter starred messages by
2839
- * @returns message object
2840
- */
2841
- getStarredMessages(chatId) {
2842
- return __awaiter(this, void 0, void 0, function* () {
2843
- return yield this.pup(chatId => WAPI.getStarredMessages(chatId), chatId);
2844
- });
2845
- }
2846
- /**
2847
- * Star a message
2848
- * @param messageId Message ID of the message you want to star
2849
- * @returns `true`
2850
- */
2851
- starMessage(messageId) {
2852
- return __awaiter(this, void 0, void 0, function* () {
2853
- return yield this.pup(messageId => WAPI.starMessage(messageId), messageId);
2854
- });
2855
- }
2856
- /**
2857
- * Unstar a message
2858
- * @param messageId Message ID of the message you want to unstar
2859
- * @returns `true`
2860
- */
2861
- unstarMessage(messageId) {
2862
- return __awaiter(this, void 0, void 0, function* () {
2863
- return yield this.pup(messageId => WAPI.unstarMessage(messageId), messageId);
2864
- });
2865
- }
2866
- /**
2867
- * React to a message
2868
- * @param messageId Message ID of the message you want to react to
2869
- * @param emoji 1 single emoji to add to the message as a reacion
2870
- * @returns boolean
2871
- */
2872
- react(messageId, emoji) {
2873
- return __awaiter(this, void 0, void 0, function* () {
2874
- return yield this.pup(({ messageId, emoji }) => WAPI.react(messageId, emoji), { messageId, emoji });
2875
- });
2876
- }
2877
- /**
2878
- * @deprecated
2879
- *
2880
- * Retrieves a message object which results in a valid sticker instead of a blank one. This also works with animated stickers.
2881
- *
2882
- * If you run this without a valid insiders key, it will return false and cause an error upon decryption.
2883
- *
2884
- * @param messageId The message ID `message.id`
2885
- * @returns message object OR `false`
2886
- */
2887
- getStickerDecryptable(messageId) {
2888
- return __awaiter(this, void 0, void 0, function* () {
2889
- const m = yield this.pup(messageId => WAPI.getStickerDecryptable(messageId), messageId);
2890
- if (!m)
2891
- return false;
2892
- return Object.assign({ t: m.t, id: m.id }, (0, wa_decrypt_1.bleachMessage)(m));
2893
- });
2894
- }
2895
- /**
2896
- *
2897
- * {@license:insiders@}
2898
- *
2899
- * If a file is old enough, it will 404 if you try to decrypt it. This will allow you to force the host account to re upload the file and return a decryptable message.
2900
- *
2901
- * if you run this without a valid insiders key, it will return false and cause an error upon decryption.
2902
- *
2903
- * @param messageId
2904
- * @returns [[Message]] OR `false`
2905
- */
2906
- forceStaleMediaUpdate(messageId) {
2907
- return __awaiter(this, void 0, void 0, function* () {
2908
- const m = yield this.pup(messageId => WAPI.forceStaleMediaUpdate(messageId), messageId);
2909
- if (!m)
2910
- return false;
2911
- return Object.assign({}, (0, wa_decrypt_1.bleachMessage)(m));
2912
- });
2913
- }
2914
- /**
2915
- * Retrieves chat object of given contact id
2916
- * @param contactId
2917
- * @returns contact detial as promise
2918
- */
2919
- getChat(contactId) {
2920
- return __awaiter(this, void 0, void 0, function* () {
2921
- return yield this.pup(contactId => WAPI.getChat(contactId), contactId);
2922
- });
2923
- }
2924
- /**
2925
- * {@license:insiders@}
2926
- *
2927
- * Retrieves the groups that you have in common with a contact
2928
- * @param contactId
2929
- */
2930
- getCommonGroups(contactId) {
2931
- return __awaiter(this, void 0, void 0, function* () {
2932
- return yield this.pup(contactId => WAPI.getCommonGroups(contactId), contactId);
2933
- });
2934
- }
2935
- /**
2936
- * Retrieves the epoch timestamp of the time the contact was last seen. This will not work if:
2937
- * 1. They have set it so you cannot see their last seen via privacy settings.
2938
- * 2. You do not have an existing chat with the contact.
2939
- * 3. The chatId is for a group
2940
- * In both of those instances this method will return undefined.
2941
- * @param chatId The id of the chat.
2942
- * @returns number timestamp when chat was last online or undefined.
2943
- */
2944
- getLastSeen(chatId) {
2945
- return __awaiter(this, void 0, void 0, function* () {
2946
- return yield this.pup(chatId => WAPI.getLastSeen(chatId), chatId);
2947
- });
2948
- }
2949
- /**
2950
- * Retrieves chat picture
2951
- * @param chatId
2952
- * @returns Url of the chat picture or undefined if there is no picture for the chat.
2953
- */
2954
- getProfilePicFromServer(chatId) {
2955
- return __awaiter(this, void 0, void 0, function* () {
2956
- return yield this.pup(chatId => WAPI.getProfilePicFromServer(chatId), chatId);
2957
- });
2958
- }
2959
- /**
2960
- * Sets a chat status to seen. Marks all messages as ack: 3
2961
- * @param chatId chat id: `xxxxx@c.us`
2962
- */
2963
- sendSeen(chatId) {
2964
- return __awaiter(this, void 0, void 0, function* () {
2965
- return yield this.pup(chatId => WAPI.sendSeen(chatId), chatId);
2966
- });
2967
- }
2968
- /**
2969
- * Runs sendSeen on all chats
2970
- */
2971
- markAllRead() {
2972
- return __awaiter(this, void 0, void 0, function* () {
2973
- return yield this.pup(() => WAPI.markAllRead());
2974
- });
2975
- }
2976
- /**
2977
- * Sets a chat status to unread. May be useful to get host's attention
2978
- * @param chatId chat id: `xxxxx@c.us`
2979
- */
2980
- markAsUnread(chatId) {
2981
- return __awaiter(this, void 0, void 0, function* () {
2982
- return yield this.pup(chatId => WAPI.markAsUnread(chatId), chatId);
2983
- });
2984
- }
2985
- /**
2986
- * Checks if a chat contact is online. Not entirely sure if this works with groups.
2987
- *
2988
- * It will return `true` if the chat is `online`, `false` if the chat is `offline`, `PRIVATE` if the privacy settings of the contact do not allow you to see their status and `NO_CHAT` if you do not currently have a chat with that contact.
2989
- *
2990
- * @param chatId chat id: `xxxxx@c.us`
2991
- */
2992
- isChatOnline(chatId) {
2993
- return __awaiter(this, void 0, void 0, function* () {
2994
- return yield this.pup(chatId => WAPI.isChatOnline(chatId), chatId);
2995
- });
2996
- }
2997
- /**
2998
- * Load more messages in chat object from server. Use this in a while loop. This should return up to 50 messages at a time
2999
- * @param contactId
3000
- * @returns Message []
3001
- */
3002
- loadEarlierMessages(contactId) {
3003
- return __awaiter(this, void 0, void 0, function* () {
3004
- return yield this.pup(contactId => WAPI.loadEarlierMessages(contactId), contactId);
3005
- });
3006
- }
3007
- /**
3008
- * Get the status of a contact
3009
- * @param contactId to '000000000000@c.us'
3010
- */
3011
- getStatus(contactId) {
3012
- return __awaiter(this, void 0, void 0, function* () {
3013
- return yield this.pup(contactId => WAPI.getStatus(contactId), contactId);
3014
- });
3015
- }
3016
- /**
3017
- *
3018
- * {@license:insiders@}
3019
- *
3020
- * :::danger
3021
- *
3022
- * Buttons are broken for the foreseeable future. Please DO NOT get a license solely for access to buttons. They are no longer reliable due to recent changes at WA.
3023
- *
3024
- * :::
3025
- *
3026
- * Use a raw payload within your open-wa session
3027
- *
3028
- * @example
3029
- * If there is a code block, then both TypeDoc and VSCode will treat
3030
- * text outside of the code block as regular text.
3031
- *
3032
- * ```ts
3033
- * await B('44123456789@c.us', {
3034
- * test: 1
3035
- * })
3036
- * ```
3037
- * {@link loadAllEarlierMessages}
3038
- * @param chatId
3039
- * @param payload
3040
- * returns: MessageId
3041
- */
3042
- B(chatId, payload) {
3043
- return __awaiter(this, void 0, void 0, function* () {
3044
- return yield this.pup(({ chatId, payload }) => WAPI.B(chatId, payload), { chatId, payload });
3045
- });
3046
- }
3047
- /**
3048
- * Load all messages in chat object from server.
3049
- * @param contactId
3050
- * @returns Message[]
3051
- */
3052
- loadAllEarlierMessages(contactId) {
3053
- return __awaiter(this, void 0, void 0, function* () {
3054
- return yield this.pup(contactId => WAPI.loadAllEarlierMessages(contactId), contactId);
3055
- });
3056
- }
3057
- /**
3058
- * Load all messages until a given timestamp in chat object from server.
3059
- * @param contactId
3060
- * @param timestamp in seconds
3061
- * @returns Message[]
3062
- */
3063
- loadEarlierMessagesTillDate(contactId, timestamp) {
3064
- return __awaiter(this, void 0, void 0, function* () {
3065
- return yield this.pup(({ contactId, timestamp }) => WAPI.loadEarlierMessagesTillDate(contactId, timestamp), { contactId, timestamp });
3066
- });
3067
- }
3068
- /**
3069
- * Delete the conversation from your WA
3070
- * @param chatId
3071
- * @returns boolean
3072
- */
3073
- deleteChat(chatId) {
3074
- return __awaiter(this, void 0, void 0, function* () {
3075
- return yield this.pup(chatId => WAPI.deleteConversation(chatId), chatId);
3076
- });
3077
- }
3078
- /**
3079
- * Delete all messages from the chat.
3080
- * @param chatId
3081
- * @returns boolean
3082
- */
3083
- clearChat(chatId) {
3084
- return __awaiter(this, void 0, void 0, function* () {
3085
- return yield this.pup(chatId => WAPI.clearChat(chatId), chatId);
3086
- });
3087
- }
3088
- /**
3089
- * Retrieves an invite link for a group chat. returns false if chat is not a group.
3090
- * @param chatId
3091
- * @returns `Promise<string>`
3092
- */
3093
- getGroupInviteLink(chatId) {
3094
- return __awaiter(this, void 0, void 0, function* () {
3095
- return yield this.pup(chatId => WAPI.getGroupInviteLink(chatId), chatId);
3096
- });
3097
- }
3098
- /**
3099
- * Get the details of a group through the invite link
3100
- * @param link This can be an invite link or invite code
3101
- * @returns
3102
- */
3103
- inviteInfo(link) {
3104
- return __awaiter(this, void 0, void 0, function* () {
3105
- return yield this.pup(link => WAPI.inviteInfo(link), link);
3106
- });
3107
- }
3108
- /**
3109
- * Set/Unset a sticker as a fav.
3110
- * @param msgId The message Id related to the sticker you want to fav
3111
- * @param fav set this to true to fav a sticker, set it to false to remove the sticker from favorites. default true
3112
- * @returns favId The ID (filehash) of the fav sticker
3113
- */
3114
- favSticker(msgId, fav = true) {
3115
- return __awaiter(this, void 0, void 0, function* () {
3116
- return yield this.pup(({ msgId, fav }) => WAPI.favSticker(msgId, fav), { msgId, fav });
3117
- });
3118
- }
3119
- /**
3120
- * Set/Unset a sticker as a fav.
3121
- * @param chatId The chat in which you want to send the sticker
3122
- * @param favId set this to true to favourite a sticker, set it to false to remove the sticker from favorites
3123
- * @returns MessageId of the sent sticker message
3124
- */
3125
- sendFavSticker(chatId, favId) {
3126
- return __awaiter(this, void 0, void 0, function* () {
3127
- return yield this.pup(({ chatId, favId }) => WAPI.sendFavSticker(chatId, favId), { chatId, favId });
3128
- });
3129
- }
3130
- /**
3131
- * Get an array of fav'ed stickers
3132
- */
3133
- getFavStickers() {
3134
- return __awaiter(this, void 0, void 0, function* () {
3135
- return yield this.pup(() => WAPI.getFavStickers());
3136
- });
3137
- }
3138
- /**
3139
- * Revokes the current invite link for a group chat. Any previous links will stop working
3140
- * @param chatId
3141
- * @returns `Promise<boolean>`
3142
- */
3143
- revokeGroupInviteLink(chatId) {
3144
- return __awaiter(this, void 0, void 0, function* () {
3145
- return yield this.pup(chatId => WAPI.revokeGroupInviteLink(chatId), chatId);
3146
- });
3147
- }
3148
- /**
3149
- * Gets the contact IDs of members requesting approval to join the group
3150
- * @param groupChatId
3151
- * @returns `Promise<ContactId[]>`
3152
- */
3153
- getGroupApprovalRequests(groupChatId) {
3154
- return __awaiter(this, void 0, void 0, function* () {
3155
- return yield this.pup(groupChatId => WAPI.getGroupApprovalRequests(groupChatId), groupChatId);
3156
- });
3157
- }
3158
- /**
3159
- * Approves a group join request
3160
- * @param groupChatId The group chat id
3161
- * @param contactId The contact id of the person who is requesting to join the group
3162
- * @returns `Promise<boolean>`
3163
- */
3164
- approveGroupJoinRequest(groupChatId, contactId) {
3165
- return __awaiter(this, void 0, void 0, function* () {
3166
- return yield this.pup(({ groupChatId, contactId }) => WAPI.approveGroupJoinRequest(groupChatId, contactId), { groupChatId, contactId });
3167
- });
3168
- }
3169
- /**
3170
- * Rejects a group join request
3171
- * @param groupChatId The group chat id
3172
- * @param contactId The contact id of the person who is requesting to join the group
3173
- * @returns `Promise<boolean>`
3174
- */
3175
- rejectGroupJoinRequest(groupChatId, contactId) {
3176
- return __awaiter(this, void 0, void 0, function* () {
3177
- return yield this.pup(({ groupChatId, contactId }) => WAPI.rejectGroupJoinRequest(groupChatId, contactId), { groupChatId, contactId });
3178
- });
3179
- }
3180
- /**
3181
- * Deletes message of given message id
3182
- * @param chatId The chat id from which to delete the message.
3183
- * @param messageId The specific message id of the message to be deleted
3184
- * @param onlyLocal If it should only delete locally (message remains on the other recipienct's phone). Defaults to false.
3185
- * @returns nothing
3186
- */
3187
- deleteMessage(chatId, messageId, onlyLocal = false) {
3188
- return __awaiter(this, void 0, void 0, function* () {
3189
- return yield this.pup(({ chatId, messageId, onlyLocal }) => WAPI.smartDeleteMessages(chatId, messageId, onlyLocal), { chatId, messageId, onlyLocal });
3190
- });
3191
- }
3192
- /**
3193
- * Checks if a number is a valid WA number
3194
- * @param contactId, you need to include the @c.us at the end.
3195
- */
3196
- checkNumberStatus(contactId) {
3197
- return __awaiter(this, void 0, void 0, function* () {
3198
- return yield this.pup(contactId => WAPI.checkNumberStatus(contactId), contactId);
3199
- });
3200
- }
3201
- /**
3202
- * Retrieves all unread Messages
3203
- * @param includeMe
3204
- * @param includeNotifications
3205
- * @param use_unread_count
3206
- * @returns any
3207
- */
3208
- getUnreadMessages(includeMe, includeNotifications, use_unread_count) {
3209
- return __awaiter(this, void 0, void 0, function* () {
3210
- return yield this.pup(({ includeMe, includeNotifications, use_unread_count }) => WAPI.getUnreadMessages(includeMe, includeNotifications, use_unread_count), { includeMe, includeNotifications, use_unread_count });
3211
- });
3212
- }
3213
- /**
3214
- * Retrieves all new Messages. where isNewMsg==true
3215
- * @returns list of messages
3216
- */
3217
- getAllNewMessages() {
3218
- return __awaiter(this, void 0, void 0, function* () {
3219
- return yield this.pup(() => WAPI.getAllNewMessages());
3220
- });
3221
- }
3222
- /**
3223
- * Retrieves all unread Messages. where ack==-1
3224
- * @returns list of messages
3225
- */
3226
- getAllUnreadMessages() {
3227
- return __awaiter(this, void 0, void 0, function* () {
3228
- return yield this.pup(() => WAPI.getAllUnreadMessages());
3229
- });
3230
- }
3231
- /**
3232
- * Retrieves all unread Messages as indicated by the red dots in WA web. This returns an array of objects and are structured like so:
3233
- * ```javascript
3234
- * [{
3235
- * "id": "000000000000@g.us", //the id of the chat
3236
- * "indicatedNewMessages": [] //array of messages, not including any messages by the host phone
3237
- * }]
3238
- * ```
3239
- * @returns list of messages
3240
- */
3241
- getIndicatedNewMessages() {
3242
- return __awaiter(this, void 0, void 0, function* () {
3243
- return JSON.parse(yield this.pup(() => WAPI.getIndicatedNewMessages()));
3244
- });
3245
- }
3246
- /**
3247
- * Fires all unread messages to the onMessage listener.
3248
- * Make sure to call this AFTER setting your listeners.
3249
- * @returns array of message IDs
3250
- */
3251
- emitUnreadMessages() {
3252
- return __awaiter(this, void 0, void 0, function* () {
3253
- return yield this.pup(() => WAPI.emitUnreadMessages());
3254
- });
3255
- }
3256
- /**
3257
- * Retrieves all Messages in a chat that have been loaded within the WA web instance.
3258
- *
3259
- * This does not load every single message in the chat history.
3260
- *
3261
- * @param chatId, the chat to get the messages from
3262
- * @param includeMe, include my own messages? boolean
3263
- * @param includeNotifications
3264
- * @returns Message[]
3265
- */
3266
- getAllMessagesInChat(chatId, includeMe, includeNotifications) {
3267
- return __awaiter(this, void 0, void 0, function* () {
3268
- return yield this.pup(({ chatId, includeMe, includeNotifications }) => WAPI.getAllMessagesInChat(chatId, includeMe, includeNotifications), { chatId, includeMe, includeNotifications });
3269
- });
3270
- }
3271
- /**
3272
- * loads and Retrieves all Messages in a chat
3273
- * @param chatId, the chat to get the messages from
3274
- * @param includeMe, include my own messages? boolean
3275
- * @param includeNotifications
3276
- * @returns any
3277
- */
3278
- loadAndGetAllMessagesInChat(chatId, includeMe, includeNotifications) {
3279
- return __awaiter(this, void 0, void 0, function* () {
3280
- return yield this.pup(({ chatId, includeMe, includeNotifications }) => WAPI.loadAndGetAllMessagesInChat(chatId, includeMe, includeNotifications), { chatId, includeMe, includeNotifications });
3281
- });
3282
- }
3283
- /**
3284
- * Create a group and add contacts to it
3285
- *
3286
- * @param groupName group name: 'New group'
3287
- * @param contacts: A single contact id or an array of contact ids.
3288
- */
3289
- createGroup(groupName, contacts) {
3290
- return __awaiter(this, void 0, void 0, function* () {
3291
- return yield this.pup(({ groupName, contacts }) => WAPI.createGroup(groupName, contacts), { groupName, contacts });
3292
- });
3293
- }
3294
- /**
3295
- * {@license:insiders@}
3296
- *
3297
- * Create a new community
3298
- *
3299
- * @param communityName The community name
3300
- * @param communitySubject: The community subject line
3301
- * @param icon DataURL of a 1:1 ratio jpeg for the community icon
3302
- * @param existingGroups An array of existing group IDs, that are not already part of a community, to add to this new community.
3303
- * @param newGroups An array of new group objects that
3304
- */
3305
- createCommunity(communityName, communitySubject, icon, existingGroups = [], newGroups) {
3306
- return __awaiter(this, void 0, void 0, function* () {
3307
- return yield this.pup(({ communityName, communitySubject, icon, existingGroups, newGroups }) => WAPI.createCommunity(communityName, communitySubject, icon, existingGroups, newGroups), { communityName, communitySubject, icon, existingGroups, newGroups });
3308
- });
3309
- }
3310
- /**
3311
- * Remove participant of Group
3312
- *
3313
- * If not a group chat, returns `NOT_A_GROUP_CHAT`.
3314
- *
3315
- * If the chat does not exist, returns `GROUP_DOES_NOT_EXIST`
3316
- *
3317
- * If the participantId does not exist in the group chat, returns `NOT_A_PARTICIPANT`
3318
- *
3319
- * If the host account is not an administrator, returns `INSUFFICIENT_PERMISSIONS`
3320
- *
3321
- * @param {*} groupId `0000000000-00000000@g.us`
3322
- * @param {*} participantId `000000000000@c.us`
3323
- */
3324
- removeParticipant(groupId, participantId) {
3325
- return __awaiter(this, void 0, void 0, function* () {
3326
- return yield this.pup(({ groupId, participantId }) => WAPI.removeParticipant(groupId, participantId), { groupId, participantId });
3327
- });
3328
- }
3329
- /** Change the icon for the group chat
3330
- * @param groupId 123123123123_1312313123@g.us The id of the group
3331
- * @param imgData 'data:image/jpeg;base64,...` The base 64 data url. Make sure this is a small img (128x128), otherwise it will fail.
3332
- * @returns boolean true if it was set, false if it didn't work. It usually doesn't work if the image file is too big.
3333
- */
3334
- setGroupIcon(groupId, image) {
3335
- return __awaiter(this, void 0, void 0, function* () {
3336
- const mimeInfo = (0, tools_1.base64MimeType)(image);
3337
- if (!mimeInfo || mimeInfo.includes("image")) {
3338
- let imgData;
3339
- imgData = yield this.stickerServerRequest('convertGroupIcon', {
3340
- image
3341
- });
3342
- return yield this.pup(({ groupId, imgData }) => WAPI.setGroupIcon(groupId, imgData), { groupId, imgData });
3343
- }
3344
- });
3345
- }
3346
- /** Change the icon for the group chat
3347
- * @param groupId 123123123123_1312313123@g.us The id of the group
3348
- * @param url'https://upload.wikimedia.org/wikipedia/commons/3/38/JPEG_example_JPG_RIP_001.jpg' The url of the image. Make sure this is a small img (128x128), otherwise it will fail.
3349
- * @param requestConfig {} By default the request is a get request, however you can override that and many other options by sending this parameter. You can read more about this parameter here: https://github.com/axios/axios#request-config
3350
- * @returns boolean true if it was set, false if it didn't work. It usually doesn't work if the image file is too big.
3351
- */
3352
- setGroupIconByUrl(groupId, url, requestConfig = {}) {
3353
- return __awaiter(this, void 0, void 0, function* () {
3354
- // eslint-disable-next-line no-useless-catch
3355
- try {
3356
- const base64 = yield (0, tools_1.getDUrl)(url, requestConfig);
3357
- return yield this.setGroupIcon(groupId, base64);
3358
- }
3359
- catch (error) {
3360
- throw error;
3361
- }
3362
- });
3363
- }
3364
- /**
3365
- * Add participant to Group
3366
- *
3367
- * If not a group chat, returns `NOT_A_GROUP_CHAT`.
3368
- *
3369
- * If the chat does not exist, returns `GROUP_DOES_NOT_EXIST`
3370
- *
3371
- * If the participantId does not exist in the contacts, returns `NOT_A_CONTACT`
3372
- *
3373
- * If the host account is not an administrator, returns `INSUFFICIENT_PERMISSIONS`
3374
- *
3375
- * @param {*} groupId '0000000000-00000000@g.us'
3376
- * @param {*} participantId '000000000000@c.us'
3377
- *
3378
- */
3379
- addParticipant(groupId, participantId) {
3380
- return __awaiter(this, void 0, void 0, function* () {
3381
- const res = yield this.pup(({ groupId, participantId }) => WAPI.addParticipant(groupId, participantId), { groupId, participantId });
3382
- if (typeof res === "object")
3383
- throw new errors_1.AddParticipantError('Unable to add some participants', res);
3384
- if (typeof res === "string")
3385
- throw new errors_1.AddParticipantError(res);
3386
- return res;
3387
- });
3388
- }
3389
- /**
3390
- * Promote Participant to Admin in Group
3391
- *
3392
- *
3393
- * If not a group chat, returns `NOT_A_GROUP_CHAT`.
3394
- *
3395
- * If the chat does not exist, returns `GROUP_DOES_NOT_EXIST`
3396
- *
3397
- * If the participantId does not exist in the group chat, returns `NOT_A_PARTICIPANT`
3398
- *
3399
- * If the host account is not an administrator, returns `INSUFFICIENT_PERMISSIONS`
3400
- *
3401
- * @param {*} groupId '0000000000-00000000@g.us'
3402
- * @param {*} participantId '000000000000@c.us'
3403
- */
3404
- promoteParticipant(groupId, participantId) {
3405
- return __awaiter(this, void 0, void 0, function* () {
3406
- return yield this.pup(({ groupId, participantId }) => WAPI.promoteParticipant(groupId, participantId), { groupId, participantId });
3407
- });
3408
- }
3409
- /**
3410
- * Demote Admin of Group
3411
- *
3412
- * If not a group chat, returns `NOT_A_GROUP_CHAT`.
3413
- *
3414
- * If the chat does not exist, returns `GROUP_DOES_NOT_EXIST`
3415
- *
3416
- * If the participantId does not exist in the group chat, returns `NOT_A_PARTICIPANT`
3417
- *
3418
- * If the host account is not an administrator, returns `INSUFFICIENT_PERMISSIONS`
3419
- *
3420
- * @param {*} groupId '0000000000-00000000@g.us'
3421
- * @param {*} participantId '000000000000@c.us'
3422
- */
3423
- demoteParticipant(groupId, participantId) {
3424
- return __awaiter(this, void 0, void 0, function* () {
3425
- return yield this.pup(({ groupId, participantId }) => WAPI.demoteParticipant(groupId, participantId), { groupId, participantId });
3426
- });
3427
- }
3428
- /**
3429
- *
3430
- * Change who can and cannot speak in a group
3431
- * @param groupId '0000000000-00000000@g.us' the group id.
3432
- * @param onlyAdmins boolean set to true if you want only admins to be able to speak in this group. false if you want to allow everyone to speak in the group
3433
- * @returns boolean true if action completed successfully.
3434
- */
3435
- setGroupToAdminsOnly(groupId, onlyAdmins) {
3436
- return __awaiter(this, void 0, void 0, function* () {
3437
- return yield this.pup(({ groupId, onlyAdmins }) => WAPI.setGroupToAdminsOnly(groupId, onlyAdmins), { groupId, onlyAdmins });
3438
- });
3439
- }
3440
- /**
3441
- *
3442
- * Change who can and cannot edit a groups details
3443
- * @param groupId '0000000000-00000000@g.us' the group id.
3444
- * @param onlyAdmins boolean set to true if you want only admins to be able to speak in this group. false if you want to allow everyone to speak in the group
3445
- * @returns boolean true if action completed successfully.
3446
- */
3447
- setGroupEditToAdminsOnly(groupId, onlyAdmins) {
3448
- return __awaiter(this, void 0, void 0, function* () {
3449
- return yield this.pup(({ groupId, onlyAdmins }) => WAPI.setGroupEditToAdminsOnly(groupId, onlyAdmins), { groupId, onlyAdmins });
3450
- });
3451
- }
3452
- /**
3453
- *
3454
- * Turn on or off the approval requirement for new members to join a group
3455
- * @param groupId '0000000000-00000000@g.us' the group id.
3456
- * @param requireApproval set to true to turn on the approval requirement, false to turn off
3457
- * @returns boolean true if action completed successfully.
3458
- */
3459
- setGroupApprovalMode(groupId, requireApproval) {
3460
- return __awaiter(this, void 0, void 0, function* () {
3461
- return yield this.pup(({ groupId, requireApproval }) => WAPI.setGroupApprovalMode(groupId, requireApproval), { groupId, requireApproval });
3462
- });
3463
- }
3464
- /**
3465
- * Change the group chant description
3466
- * @param groupId '0000000000-00000000@g.us' the group id.
3467
- * @param description string The new group description
3468
- * @returns boolean true if action completed successfully.
3469
- */
3470
- setGroupDescription(groupId, description) {
3471
- return __awaiter(this, void 0, void 0, function* () {
3472
- return yield this.pup(({ groupId, description }) => WAPI.setGroupDescription(groupId, description), { groupId, description });
3473
- });
3474
- }
3475
- /**
3476
- * {@license:insiders@}
3477
- *
3478
- * Change the group chat title
3479
- * @param groupId '0000000000-00000000@g.us' the group id.
3480
- * @param title string The new group title
3481
- * @returns boolean true if action completed successfully.
3482
- */
3483
- setGroupTitle(groupId, title) {
3484
- return __awaiter(this, void 0, void 0, function* () {
3485
- return yield this.pup(({ groupId, title }) => WAPI.setGroupTitle(groupId, title), { groupId, title });
3486
- });
3487
- }
3488
- /**
3489
- * Get Admins of a Group
3490
- * @param {*} groupId '0000000000-00000000@g.us'
3491
- */
3492
- getGroupAdmins(groupId) {
3493
- return __awaiter(this, void 0, void 0, function* () {
3494
- return yield this.pup((groupId) => WAPI.getGroupAdmins(groupId), groupId);
3495
- });
3496
- }
3497
- /**
3498
- * {@license:insiders@}
3499
- *
3500
- * Set the wallpaper background colour
3501
- * @param {string} hex '#FFF123'
3502
- */
3503
- setChatBackgroundColourHex(hex) {
3504
- return __awaiter(this, void 0, void 0, function* () {
3505
- return yield this.pup((hex) => WAPI.setChatBackgroundColourHex(hex), hex);
3506
- });
3507
- }
3508
- /**
3509
- * Join or leave the wa web beta program. Will return true of operation was successful.
3510
- *
3511
- * @param {boolean} join true to join the beta, false to leave
3512
- */
3513
- joinWebBeta(join) {
3514
- return __awaiter(this, void 0, void 0, function* () {
3515
- return yield this.pup((join) => WAPI.joinWebBeta(join), join);
3516
- });
3517
- }
3518
- /**
3519
- *
3520
- * Start dark mode [NOW GENERALLY AVAILABLE]
3521
- * @param {boolean} activate true to activate dark mode, false to deactivate
3522
- */
3523
- darkMode(activate) {
3524
- return __awaiter(this, void 0, void 0, function* () {
3525
- return yield this.pup((activate) => WAPI.darkMode(activate), activate);
3526
- });
3527
- }
3528
- /**
3529
- *
3530
- * Automatically reject calls on the host account device. Please note that the device that is calling you will continue to ring.
3531
- *
3532
- * Update: Due to the nature of MD, the host account will continue ringing.
3533
- *
3534
- * @param message optional message to send to the calling account when their call is detected and rejected
3535
- */
3536
- autoReject(message) {
3537
- return __awaiter(this, void 0, void 0, function* () {
3538
- return yield this.pup((message) => WAPI.autoReject(message), message);
3539
- });
3540
- }
3541
- /**
3542
- * Returns an array of contacts that have read the message. If the message does not exist, it will return an empty array. If the host account has disabled read receipts this may not work!
3543
- * Each of these contact objects have a property `t` which represents the time at which that contact read the message.
3544
- * @param messageId The message id
3545
- */
3546
- getMessageReaders(messageId) {
3547
- return __awaiter(this, void 0, void 0, function* () {
3548
- return yield this.pup((messageId) => WAPI.getMessageReaders(messageId), messageId);
3549
- });
3550
- }
3551
- /**
3552
- * Returns poll data including results and votes.
3553
- *
3554
- * @param messageId The message id of the Poll
3555
- */
3556
- getPollData(messageId) {
3557
- return __awaiter(this, void 0, void 0, function* () {
3558
- return yield this.pup((messageId) => WAPI.getPollData(messageId), messageId);
3559
- });
3560
- }
3561
- /**
3562
- * Sends a sticker (including GIF) from a given URL
3563
- * @param to: The recipient id.
3564
- * @param url: The url of the image
3565
- * @param requestConfig {} By default the request is a get request, however you can override that and many other options by sending this parameter. You can read more about this parameter here: https://github.com/axios/axios#request-config
3566
- *
3567
- * @returns `Promise<MessageId | boolean>`
3568
- */
3569
- sendStickerfromUrl(to, url, requestConfig = {}, stickerMetadata) {
3570
- return __awaiter(this, void 0, void 0, function* () {
3571
- const base64 = yield (0, tools_1.getDUrl)(url, requestConfig);
3572
- return yield this.sendImageAsSticker(to, base64, stickerMetadata);
3573
- });
3574
- }
3575
- /**
3576
- * {@license:insiders@}
3577
- *
3578
- * Sends a sticker from a given URL
3579
- * @param to The recipient id.
3580
- * @param url The url of the image
3581
- * @param messageId The id of the message to reply to
3582
- * @param requestConfig {} By default the request is a get request, however you can override that and many other options by sending this parameter. You can read more about this parameter here: https://github.com/axios/axios#request-config
3583
- *
3584
- * @returns `Promise<MessageId | boolean>`
3585
- */
3586
- sendStickerfromUrlAsReply(to, url, messageId, requestConfig = {}, stickerMetadata) {
3587
- return __awaiter(this, void 0, void 0, function* () {
3588
- const dUrl = yield (0, tools_1.getDUrl)(url, requestConfig);
3589
- const processingResponse = yield this.prepareWebp(dUrl, stickerMetadata);
3590
- if (!processingResponse)
3591
- return false;
3592
- const { webpBase64, metadata } = processingResponse;
3593
- return yield this.pup(({ webpBase64, to, metadata, messageId }) => WAPI.sendStickerAsReply(webpBase64, to, metadata, messageId), { webpBase64, to, metadata, messageId });
3594
- });
3595
- }
3596
- /**
3597
- * {@license:insiders@}
3598
- *
3599
- * This function takes an image and sends it as a sticker to the recipient as a reply to another message.
3600
- *
3601
- *
3602
- * @param to The recipient id.
3603
- * @param image: [[DataURL]], [[Base64]], URL (string GET), Relative filepath (string), or Buffer of the image
3604
- * @param messageId The id of the message to reply to
3605
- * @param stickerMetadata Sticker metadata
3606
- */
3607
- sendImageAsStickerAsReply(to, image, messageId, stickerMetadata) {
3608
- return __awaiter(this, void 0, void 0, function* () {
3609
- //@ts-ignore
3610
- if ((Buffer.isBuffer(image) || typeof image === 'object' || (image === null || image === void 0 ? void 0 : image.type) === 'Buffer') && image.toString) {
3611
- image = image.toString('base64');
3612
- }
3613
- else if (typeof image === 'string') {
3614
- if (!(0, tools_1.isDataURL)(image) && !(0, tools_1.isBase64)(image)) {
3615
- //must be a file then
3616
- if ((0, is_url_superb_1.default)(image)) {
3617
- image = yield (0, tools_1.getDUrl)(image);
3618
- }
3619
- else {
3620
- const relativePath = path.join(path.resolve(process.cwd(), image || ''));
3621
- if (fs.existsSync(image) || fs.existsSync(relativePath)) {
3622
- image = yield (0, datauri_1.default)(fs.existsSync(image) ? image : relativePath);
3623
- }
3624
- else
3625
- return 'FILE_NOT_FOUND';
3626
- }
3627
- }
3628
- }
3629
- const processingResponse = yield this.prepareWebp(image, stickerMetadata);
3630
- if (!processingResponse)
3631
- return false;
3632
- const { webpBase64, metadata } = processingResponse;
3633
- return yield this.pup(({ webpBase64, to, metadata, messageId }) => WAPI.sendStickerAsReply(webpBase64, to, metadata, messageId), { webpBase64, to, metadata, messageId });
3634
- });
3635
- }
3636
- /**
3637
- * This allows you to get a single property of a single object from the session. This limints the amouunt of data you need to sift through, reduces congestion between your process and the session and the flexibility to build your own specific getters.
3638
- *
3639
- * Example - get message read state (ack):
3640
- *
3641
- * ```javascript
3642
- * const ack = await client.getSingleProperty('Msg',"true_12345678912@c.us_9C4D0965EA5C09D591334AB6BDB07FEB",'ack')
3643
- * ```
3644
- * @param namespace
3645
- * @param id id of the object to get from the specific namespace
3646
- * @param property the single property key to get from the object.
3647
- * @returns any If the property or the id cannot be found, it will return a 404
3648
- */
3649
- getSingleProperty(namespace, id, property) {
3650
- return __awaiter(this, void 0, void 0, function* () {
3651
- return yield this.pup(({ namespace, id, property }) => WAPI.getSingleProperty(namespace, id, property), { namespace, id, property });
3652
- });
3653
- }
3654
- stickerServerRequest(func, a = {}, fallback = false) {
3655
- var _a, _b, _c, _d;
3656
- return __awaiter(this, void 0, void 0, function* () {
3657
- const stickerUrl = this._createConfig.stickerServerEndpoint || (fallback ? pkg.stickerUrl : "https://sticker-api.openwa.dev") || "https://sticker-api.openwa.dev";
3658
- if (func === 'convertMp4BufferToWebpDataUrl')
3659
- fallback = true;
3660
- const sessionInfo = this.getSessionInfo();
3661
- sessionInfo.WA_AUTOMATE_VERSION = sessionInfo.WA_AUTOMATE_VERSION.split(' ')[0];
3662
- if (a.file || a.image || a.emojiId) {
3663
- if (!a.emojiId) {
3664
- //check if its a local file:
3665
- const key = a.file ? 'file' : 'image';
3666
- if (!(0, tools_1.isDataURL)(a[key]) && !(0, is_url_superb_1.default)(a[key]) && !(0, tools_1.isBase64)(a[key])) {
3667
- const relativePath = path.join(path.resolve(process.cwd(), a[key] || ''));
3668
- if (fs.existsSync(a[key]) || fs.existsSync(relativePath)) {
3669
- a[key] = yield (0, datauri_1.default)(fs.existsSync(a[key]) ? a[key] : relativePath);
3670
- }
3671
- else {
3672
- console.error('FILE_NOT_FOUND');
3673
- throw new errors_1.CustomError(errors_1.ERROR_NAME.FILE_NOT_FOUND, 'FILE NOT FOUND');
3674
- }
3675
- }
3676
- if ((a === null || a === void 0 ? void 0 : a.stickerMetadata) && typeof (a === null || a === void 0 ? void 0 : a.stickerMetadata) !== "object")
3677
- throw new errors_1.CustomError(errors_1.ERROR_NAME.BAD_STICKER_METADATA, `Received ${typeof (a === null || a === void 0 ? void 0 : a.stickerMetadata)}: ${a === null || a === void 0 ? void 0 : a.stickerMetadata}`);
3678
- }
3679
- if ((_a = this._createConfig) === null || _a === void 0 ? void 0 : _a.discord) {
3680
- a.stickerMetadata = Object.assign(Object.assign({}, (a.stickerMetadata || {})), { discord: `${((_b = a.stickerMetadata) === null || _b === void 0 ? void 0 : _b.discord) || this._createConfig.discord}` });
3681
- }
3682
- try {
3683
- const url = `${stickerUrl.replace(/\/$/, '')}/${func}`;
3684
- logging_1.log.info(`Requesting sticker from ${url}`);
3685
- const { data } = yield axios_1.default.post(url, Object.assign(Object.assign({}, a), { sessionInfo, config: this.getConfig() }), {
3686
- maxBodyLength: 20000000,
3687
- maxContentLength: 1500000 // 1.5mb response body limit
3688
- });
3689
- return data;
3690
- }
3691
- catch (err) {
3692
- if (err === null || err === void 0 ? void 0 : err.message.includes("maxContentLength size")) {
3693
- throw new errors_1.CustomError(errors_1.ERROR_NAME.STICKER_TOO_LARGE, err === null || err === void 0 ? void 0 : err.message);
3694
- }
3695
- else if (!fallback) {
3696
- return yield this.stickerServerRequest(func, a, true);
3697
- }
3698
- console.error((_c = err === null || err === void 0 ? void 0 : err.response) === null || _c === void 0 ? void 0 : _c.status, (_d = err === null || err === void 0 ? void 0 : err.response) === null || _d === void 0 ? void 0 : _d.data);
3699
- throw err;
3700
- return false;
3701
- }
3702
- }
3703
- else {
3704
- console.error("Media is missing from this request");
3705
- throw new errors_1.CustomError(errors_1.ERROR_NAME.MEDIA_MISSING, "Media is missing from this request");
3706
- }
3707
- });
3708
- }
3709
- prepareWebp(image, stickerMetadata) {
3710
- return __awaiter(this, void 0, void 0, function* () {
3711
- if ((0, tools_1.isDataURL)(image) && !image.includes("image")) {
3712
- console.error("Not an image. Please use convertMp4BufferToWebpDataUrl to process video stickers");
3713
- return false;
3714
- }
3715
- return yield this.stickerServerRequest('prepareWebp', {
3716
- image,
3717
- stickerMetadata
3718
- });
3719
- });
3720
- }
3721
- /**
3722
- * This function takes an image (including animated GIF) and sends it as a sticker to the recipient. This is helpful for sending semi-ephemeral things like QR codes.
3723
- * The advantage is that it will not show up in the recipients gallery. This function automatiicaly converts images to the required webp format.
3724
- * @param to: The recipient id.
3725
- * @param image: [[DataURL]], [[Base64]], URL (string GET), Relative filepath (string), or Buffer of the image
3726
- */
3727
- sendImageAsSticker(to, image, stickerMetadata) {
3728
- return __awaiter(this, void 0, void 0, function* () {
3729
- //@ts-ignore
3730
- if ((Buffer.isBuffer(image) || typeof image === 'object' || (image === null || image === void 0 ? void 0 : image.type) === 'Buffer') && image.toString) {
3731
- image = image.toString('base64');
3732
- }
3733
- else if (typeof image === 'string') {
3734
- if (!(0, tools_1.isDataURL)(image) && !(0, tools_1.isBase64)(image)) {
3735
- //must be a file then
3736
- if ((0, is_url_superb_1.default)(image)) {
3737
- image = yield (0, tools_1.getDUrl)(image);
3738
- }
3739
- else {
3740
- const relativePath = path.join(path.resolve(process.cwd(), image || ''));
3741
- if (fs.existsSync(image) || fs.existsSync(relativePath)) {
3742
- image = yield (0, datauri_1.default)(fs.existsSync(image) ? image : relativePath);
3743
- }
3744
- else
3745
- return 'FILE_NOT_FOUND';
3746
- }
3747
- }
3748
- }
3749
- const processingResponse = yield this.prepareWebp(image, stickerMetadata);
3750
- if (!processingResponse)
3751
- return false;
3752
- const { webpBase64, metadata } = processingResponse;
3753
- return yield this.pup(({ webpBase64, to, metadata }) => WAPI.sendImageAsSticker(webpBase64, to, metadata), { webpBase64, to, metadata });
3754
- });
3755
- }
3756
- /**
3757
- * Use this to send an mp4 file as a sticker. This can also be used to convert GIFs from the chat because GIFs in WA are actually tiny mp4 files.
3758
- *
3759
- * @param to ChatId The chat id you want to send the webp sticker to
3760
- * @param file [[DataURL]], [[Base64]], URL (string GET), Relative filepath (string), or Buffer of the mp4 file
3761
- * @param messageId message id of the message you want this sticker to reply to. @license:insiders@
3762
- */
3763
- sendMp4AsSticker(to, file, processOptions = media_1.defaultProcessOptions, stickerMetadata, messageId) {
3764
- return __awaiter(this, void 0, void 0, function* () {
3765
- //@ts-ignore
3766
- if ((Buffer.isBuffer(file) || typeof file === 'object' || (file === null || file === void 0 ? void 0 : file.type) === 'Buffer') && file.toString) {
3767
- file = file.toString('base64');
3768
- }
3769
- if (typeof file === 'string') {
3770
- if (!(0, tools_1.isDataURL)(file) && !(0, tools_1.isBase64)(file)) {
3771
- //must be a file then
3772
- if ((0, is_url_superb_1.default)(file)) {
3773
- file = yield (0, tools_1.getDUrl)(file);
3774
- }
3775
- else {
3776
- const relativePath = path.join(path.resolve(process.cwd(), file || ''));
3777
- if (fs.existsSync(file) || fs.existsSync(relativePath)) {
3778
- file = yield (0, datauri_1.default)(fs.existsSync(file) ? file : relativePath);
3779
- }
3780
- else
3781
- return 'FILE_NOT_FOUND';
3782
- }
3783
- }
3784
- }
3785
- const convertedStickerDataUrl = yield this.stickerServerRequest('convertMp4BufferToWebpDataUrl', {
3786
- file,
3787
- processOptions,
3788
- stickerMetadata
3789
- });
3790
- try {
3791
- if (!convertedStickerDataUrl)
3792
- return false;
3793
- return (yield (messageId && this._createConfig.licenseKey)) ? this.sendRawWebpAsStickerAsReply(to, messageId, convertedStickerDataUrl, true) : this.sendRawWebpAsSticker(to, convertedStickerDataUrl, true);
3794
- }
3795
- catch (error) {
3796
- const msg = 'Stickers have to be less than 1MB. Please lower the fps or shorten the duration using the processOptions parameter: https://open-wa.github.io/wa-automate-nodejs/classes/client.html#sendmp4assticker';
3797
- console.log(msg);
3798
- logging_1.log.warn(msg);
3799
- throw new errors_1.CustomError(errors_1.ERROR_NAME.STICKER_TOO_LARGE, msg);
3800
- }
3801
- });
3802
- }
3803
- /**
3804
- * Send a discord emoji to a chat as a sticker
3805
- *
3806
- * @param to ChatId The chat id you want to send the webp sticker to
3807
- * @param emojiId The discord emoji id without indentifying chars. In discord you would write `:who:`, here use `who`
3808
- * @param messageId message id of the message you want this sticker to reply to. @license:insiders@
3809
- */
3810
- sendEmoji(to, emojiId, messageId) {
3811
- return __awaiter(this, void 0, void 0, function* () {
3812
- const webp = yield this.stickerServerRequest('emoji', {
3813
- emojiId
3814
- });
3815
- if (webp) {
3816
- if (messageId)
3817
- return yield this.sendRawWebpAsStickerAsReply(to, messageId, webp, true);
3818
- return yield this.sendRawWebpAsSticker(to, webp, true);
3819
- }
3820
- return false;
3821
- });
3822
- }
3823
- /**
3824
- * You can use this to send a raw webp file.
3825
- * @param to ChatId The chat id you want to send the webp sticker to
3826
- * @param webpBase64 Base64 The base64 string of the webp file. Not DataURl
3827
- * @param animated Boolean Set to true if the webp is animated. Default `false`
3828
- */
3829
- sendRawWebpAsSticker(to, webpBase64, animated = false) {
3830
- return __awaiter(this, void 0, void 0, function* () {
3831
- const metadata = {
3832
- format: 'webp',
3833
- width: 512,
3834
- height: 512,
3835
- animated,
3836
- };
3837
- webpBase64 = webpBase64.replace(/^data:image\/(png|gif|jpeg|webp|octet-stream);base64,/, '');
3838
- return yield this.pup(({ webpBase64, to, metadata }) => WAPI.sendImageAsSticker(webpBase64, to, metadata), { webpBase64, to, metadata });
3839
- });
3840
- }
3841
- /**
3842
- * {@license:insiders@}
3843
- *
3844
- * You can use this to send a raw webp file.
3845
- * @param to ChatId The chat id you want to send the webp sticker to
3846
- * @param messageId MessageId Message ID of the message to reply to
3847
- * @param webpBase64 Base64 The base64 string of the webp file. Not DataURl
3848
- * @param animated Boolean Set to true if the webp is animated. Default `false`
3849
- */
3850
- sendRawWebpAsStickerAsReply(to, messageId, webpBase64, animated = false) {
3851
- return __awaiter(this, void 0, void 0, function* () {
3852
- const metadata = {
3853
- format: 'webp',
3854
- width: 512,
3855
- height: 512,
3856
- animated,
3857
- };
3858
- webpBase64 = webpBase64.replace(/^data:image\/(png|gif|jpeg|webp);base64,/, '');
3859
- return yield this.pup(({ webpBase64, to, metadata, messageId }) => WAPI.sendStickerAsReply(webpBase64, to, metadata, messageId), { webpBase64, to, metadata, messageId });
3860
- });
3861
- }
3862
- /**
3863
- * {@license:insiders@}
3864
- *
3865
- * Turn the ephemeral setting in a chat to on or off
3866
- * @param chatId The ID of the chat
3867
- * @param ephemeral `true` to turn on the ephemeral setting to 1 day, `false` to turn off the ephemeral setting. Other options: `604800 | 7776000`
3868
- * @returns `Promise<boolean>` true if the setting was set, `false` if the chat does not exist
3869
- */
3870
- setChatEphemeral(chatId, ephemeral) {
3871
- return __awaiter(this, void 0, void 0, function* () {
3872
- return yield this.pup(({ chatId, ephemeral }) => WAPI.setChatEphemeral(chatId, ephemeral), { chatId, ephemeral });
3873
- });
3874
- }
3875
- /**
3876
- * Send a giphy GIF as an animated sticker.
3877
- * @param to ChatId
3878
- * @param giphyMediaUrl URL | string This is the giphy media url and has to be in the format `https://media.giphy.com/media/RJKHjCAdsAfQPn03qQ/source.gif` or it can be just the id `RJKHjCAdsAfQPn03qQ`
3879
- */
3880
- sendGiphyAsSticker(to, giphyMediaUrl) {
3881
- return __awaiter(this, void 0, void 0, function* () {
3882
- return yield this.pup(({ to, giphyMediaUrl }) => WAPI.sendGiphyAsSticker(to, giphyMediaUrl), { to, giphyMediaUrl });
3883
- });
3884
- }
3885
- /**
3886
- * {@license:restricted@}
3887
- *
3888
- * Sends a formatted text story.
3889
- * @param text The text to be displayed in the story
3890
- * @param textRgba The colour of the text in the story in hex format, make sure to add the alpha value also. E.g "#FF00F4F2"
3891
- * @param backgroundRgba The colour of the background in the story in hex format, make sure to add the alpha value also. E.g "#4FF31FF2"
3892
- * @param font The font of the text to be used in the story. This has to be a number. Each number refers to a specific predetermined font. Here are the fonts you can choose from:
3893
- * 0: Sans Serif
3894
- * 1: Serif
3895
- * 2: [Norican Regular](https://fonts.google.com/specimen/Norican)
3896
- * 3: [Bryndan Write](https://www.dafontfree.net/freefonts-bryndan-write-f160189.htm)
3897
- * 4: [Bebasneue Regular](https://www.dafont.com/bebas-neue.font)
3898
- * 5: [Oswald Heavy](https://www.fontsquirrel.com/fonts/oswald)
3899
- * @returns `Promise<string | boolean>` returns status id if it worked, false if it didn't
3900
- */
3901
- postTextStatus(text, textRgba, backgroundRgba, font) {
3902
- return __awaiter(this, void 0, void 0, function* () {
3903
- return yield this.pup(({ text, textRgba, backgroundRgba, font }) => WAPI.postTextStatus(text, textRgba, backgroundRgba, font), { text, textRgba, backgroundRgba, font });
3904
- });
3905
- }
3906
- /**
3907
- * {@license:restricted@}
3908
- *
3909
- * Sends a formatted text story with a thumbnail.
3910
- * @param url The URL to share in the story
3911
- * @param text The text to be displayed in the story
3912
- * @param textRgba The colour of the text in the story in hex format, make sure to add the alpha value also. E.g "#FF00F4F2"
3913
- * @param backgroundRgba The colour of the background in the story in hex format, make sure to add the alpha value also. E.g "#4FF31FF2"
3914
- * @param font The font of the text to be used in the story. This has to be a number. Each number refers to a specific predetermined font. Here are the fonts you can choose from:
3915
- * @param thumbnail base64 thumbnail override, if not provided the link server will try to figure it out.
3916
- * 0: Sans Serif
3917
- * 1: Serif
3918
- * 2: [Norican Regular](https://fonts.google.com/specimen/Norican)
3919
- * 3: [Bryndan Write](https://www.dafontfree.net/freefonts-bryndan-write-f160189.htm)
3920
- * @returns `Promise<MessageId>` returns status id if it worked, false if it didn't
3921
- */
3922
- postThumbnailStatus(url, text, textRgba, backgroundRgba, font, thumbnail) {
3923
- var _a;
3924
- return __awaiter(this, void 0, void 0, function* () {
3925
- let linkData;
3926
- let thumb = thumbnail;
3927
- try {
3928
- linkData = (yield axios_1.default.get(`${((_a = this._createConfig) === null || _a === void 0 ? void 0 : _a.linkParser) || "https://link.openwa.cloud/api"}?url=${url}`)).data;
3929
- logging_1.log.info("Got link data");
3930
- if (!thumbnail)
3931
- thumb = yield (0, tools_1.getDUrl)(linkData.image);
3932
- }
3933
- catch (error) {
3934
- console.error(error);
3935
- }
3936
- const { title, description } = linkData;
3937
- return yield this.pup(({ thumb, url, title, description, text, textRgba, backgroundRgba, font }) => WAPI.sendStoryWithThumb(thumb, url, title, description, text, textRgba, backgroundRgba, font), { thumb, url, title, description, text, textRgba, backgroundRgba, font });
3938
- });
3939
- }
3940
- /**
3941
- * {@license:restricted@}
3942
- *
3943
- * Posts an image story.
3944
- * @param data data url string `data:[<MIME-type>][;charset=<encoding>][;base64],<data>`
3945
- * @param caption The caption for the story
3946
- * @returns `Promise<string | boolean>` returns status id if it worked, false if it didn't
3947
- */
3948
- postImageStatus(data, caption) {
3949
- return __awaiter(this, void 0, void 0, function* () {
3950
- return yield this.pup(({ data, caption }) => WAPI.postImageStatus(data, caption), { data, caption });
3951
- });
3952
- }
3953
- /**
3954
- * {@license:restricted@}
3955
- *
3956
- * Posts a video story.
3957
- * @param data data url string `data:[<MIME-type>][;charset=<encoding>][;base64],<data>`
3958
- * @param caption The caption for the story
3959
- * @returns `Promise<string | boolean>` returns status id if it worked, false if it didn't
3960
- */
3961
- postVideoStatus(data, caption) {
3962
- return __awaiter(this, void 0, void 0, function* () {
3963
- return yield this.pup(({ data, caption }) => WAPI.postVideoStatus(data, caption), { data, caption });
3964
- });
3965
- }
3966
- /**
3967
- * {@license:restricted@}
3968
- *
3969
- * Consumes a list of id strings of stories to delete.
3970
- *
3971
- * @param statusesToDelete string [] | string an array of ids of stories to delete.
3972
- * @returns boolean. True if it worked.
3973
- */
3974
- deleteStory(statusesToDelete) {
3975
- return __awaiter(this, void 0, void 0, function* () {
3976
- return yield this.pup(({ statusesToDelete }) => WAPI.deleteStatus(statusesToDelete), { statusesToDelete });
3977
- });
3978
- }
3979
- /**
3980
- * Alias for deleteStory
3981
- */
3982
- deleteStatus(statusesToDelete) {
3983
- return __awaiter(this, void 0, void 0, function* () {
3984
- return yield this.deleteStory(statusesToDelete);
3985
- });
3986
- }
3987
- /**
3988
- * {@license:restricted@}
3989
- *
3990
- * Deletes all your existing stories.
3991
- * @returns boolean. True if it worked.
3992
- */
3993
- deleteAllStories() {
3994
- return __awaiter(this, void 0, void 0, function* () {
3995
- return yield this.pup(() => WAPI.deleteAllStatus());
3996
- });
3997
- }
3998
- /**
3999
- * Alias for deleteStory
4000
- */
4001
- deleteAllStatus() {
4002
- return __awaiter(this, void 0, void 0, function* () {
4003
- return yield this.deleteAllStories();
4004
- });
4005
- }
4006
- /**
4007
- * {@license:restricted@}
4008
- *
4009
- * Retrieves all existing stories.
4010
- *
4011
- * Only works with a Story License Key
4012
- */
4013
- getMyStoryArray() {
4014
- return __awaiter(this, void 0, void 0, function* () {
4015
- return yield this.pup(() => WAPI.getMyStatusArray());
4016
- });
4017
- }
4018
- /**
4019
- * Alias for deleteStory
4020
- */
4021
- getMyStatusArray() {
4022
- return __awaiter(this, void 0, void 0, function* () {
4023
- return yield this.getMyStoryArray();
4024
- });
4025
- }
4026
- /**
4027
- * {@license:restricted@}
4028
- *
4029
- * Retrieves an array of user ids that have 'read' your story.
4030
- *
4031
- * @param id string The id of the story
4032
- *
4033
- */
4034
- getStoryViewers(id) {
4035
- return __awaiter(this, void 0, void 0, function* () {
4036
- return yield this.pup(({ id }) => WAPI.getStoryViewers(id), { id });
4037
- });
4038
- }
4039
- /**
4040
- * Clears all chats of all messages. This does not delete chats. Please be careful with this as it will remove all messages from whatsapp web and the host device. This feature is great for privacy focussed bots.
4041
- *
4042
- * @param ts number A chat that has had a message after ts (epoch timestamp) will not be cleared.
4043
- *
4044
- */
4045
- clearAllChats(ts) {
4046
- return __awaiter(this, void 0, void 0, function* () {
4047
- return yield this.pup(({ ts }) => WAPI.clearAllChats(ts), { ts });
4048
- });
4049
- }
4050
- /**
4051
- * This simple function halves the amount of messages in your session message cache. This does not delete messages off your phone. If over a day you've processed 4000 messages this will possibly result in 4000 messages being present in your session.
4052
- * Calling this method will cut the message cache to 2000 messages, therefore reducing the memory usage of your process.
4053
- * You should use this in conjunction with `getAmountOfLoadedMessages` to intelligently control the session message cache.
4054
- */
4055
- cutMsgCache() {
4056
- return __awaiter(this, void 0, void 0, function* () {
4057
- return yield this.pup(() => WAPI.cutMsgCache());
4058
- });
4059
- }
4060
- /**
4061
- * This simple function halves the amount of chats in your session message cache. This does not delete messages off your phone. If over a day you've processed 4000 messages this will possibly result in 4000 messages being present in your session.
4062
- * Calling this method will cut the message cache as much as possible, reducing the memory usage of your process.
4063
- * You should use this in conjunction with `getAmountOfLoadedMessages` to intelligently control the session message cache.
4064
- */
4065
- cutChatCache() {
4066
- return __awaiter(this, void 0, void 0, function* () {
4067
- return yield this.pup(() => WAPI.cutChatCache());
4068
- });
4069
- }
4070
- /**
4071
- * Deletes chats from a certain index (default 1000). E.g if this startingFrom param is `100` then all chats from index `100` onwards will be deleted.
4072
- *
4073
- * @param startingFrom the chat index to start from. Please do not set this to anything less than 10 @default: `1000`
4074
- */
4075
- deleteStaleChats(startingFrom) {
4076
- return __awaiter(this, void 0, void 0, function* () {
4077
- return yield this.pup(({ startingFrom }) => WAPI.deleteStaleChats(startingFrom), { startingFrom });
4078
- });
4079
- }
4080
- /**
4081
- * Download profile pics from the message object.
4082
- * ```javascript
4083
- * const filename = `profilepic_${message.from}.jpeg`;
4084
- * const data = await client.downloadProfilePicFromMessage(message);
4085
- * const dataUri = `data:image/jpeg;base64,${data}`;
4086
- * fs.writeFile(filename, mData, 'base64', function(err) {
4087
- * if (err) {
4088
- * return console.log(err);
4089
- * }
4090
- * console.log('The file was saved!');
4091
- * });
4092
- * ```
4093
- */
4094
- downloadProfilePicFromMessage(message) {
4095
- return __awaiter(this, void 0, void 0, function* () {
4096
- return yield this.downloadFileWithCredentials(message.sender.profilePicThumbObj.imgFull);
4097
- });
4098
- }
4099
- /**
4100
- * Download via the browsers authenticated session via URL.
4101
- * @returns base64 string (non-data url)
4102
- */
4103
- downloadFileWithCredentials(url) {
4104
- return __awaiter(this, void 0, void 0, function* () {
4105
- if (!url)
4106
- throw new errors_1.CustomError(errors_1.ERROR_NAME.MISSING_URL, 'Missing URL');
4107
- return yield this.pup(({ url }) => WAPI.downloadFileWithCredentials(url), { url });
4108
- });
4109
- }
4110
- /**
4111
- *
4112
- * Sets the profile pic of the host number.
4113
- * @param data string data url image string.
4114
- * @returns `Promise<boolean>` success if true
4115
- */
4116
- setProfilePic(data) {
4117
- return __awaiter(this, void 0, void 0, function* () {
4118
- return yield this.pup(({ data }) => WAPI.setProfilePic(data), { data });
4119
- });
4120
- }
4121
- /**
4122
- * Retreives an array of webhook objects
4123
- */
4124
- listWebhooks() {
4125
- return __awaiter(this, void 0, void 0, function* () {
4126
- return this._registeredWebhooks ? Object.keys(this._registeredWebhooks).map(id => this._registeredWebhooks[id]).map((_a) => {
4127
- var {
4128
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
4129
- requestConfig } = _a, rest = __rest(_a, ["requestConfig"]);
4130
- return rest;
4131
- }) : [];
4132
- });
4133
- }
4134
- /**
4135
- * Removes a webhook.
4136
- *
4137
- * Returns `true` if the webhook was found and removed. `false` if the webhook was not found and therefore could not be removed. This does not unregister any listeners off of other webhooks.
4138
- *
4139
- *
4140
- * @param webhookId The ID of the webhook
4141
- * @retruns boolean
4142
- */
4143
- removeWebhook(webhookId) {
4144
- return __awaiter(this, void 0, void 0, function* () {
4145
- if (this._registeredWebhooks[webhookId]) {
4146
- delete this._registeredWebhooks[webhookId];
4147
- return true; //`Webhook for ${simpleListener} removed`
4148
- }
4149
- return false; //`Webhook for ${simpleListener} not found`
4150
- });
4151
- }
4152
- /**
4153
- * Update registered events for a specific webhook. This will override all existing events. If you'd like to remove all listeners from a webhook, consider using [[removeWebhook]].
4154
- *
4155
- * In order to update authentication details for a webhook, remove it completely and then reregister it with the correct credentials.
4156
- */
4157
- updateWebhook(webhookId, events) {
4158
- return __awaiter(this, void 0, void 0, function* () {
4159
- if (events === "all")
4160
- events = Object.keys(events_2.SimpleListener).map(eventKey => events_2.SimpleListener[eventKey]);
4161
- if (!Array.isArray(events))
4162
- events = [events];
4163
- const validListeners = yield this._setupWebhooksOnListeners(events);
4164
- if (this._registeredWebhooks[webhookId]) {
4165
- this._registeredWebhooks[webhookId].events = validListeners;
4166
- const _a = this._registeredWebhooks[webhookId], {
4167
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
4168
- requestConfig } = _a, rest = __rest(_a, ["requestConfig"]);
4169
- return rest;
4170
- }
4171
- return false;
4172
- });
4173
- }
4174
- /**
4175
- * The client can now automatically handle webhooks. Use this method to register webhooks.
4176
- *
4177
- * @param event use [[SimpleListener]] enum
4178
- * @param url The webhook url
4179
- * @param requestConfig {} By default the request is a post request, however you can override that and many other options by sending this parameter. You can read more about this parameter here: https://github.com/axios/axios#request-config
4180
- * @param concurrency the amount of concurrent requests to be handled by the built in queue. Default is 5.
4181
- */
4182
- // public async registerWebhook(event: SimpleListener, url: string, requestConfig: AxiosRequestConfig = {}, concurrency: number = 5) {
4183
- // if(!this._webhookQueue) this._webhookQueue = new PQueue({ concurrency });
4184
- // if(this[event]){
4185
- // if(!this._registeredWebhooks) this._registeredWebhooks={};
4186
- // if(this._registeredWebhooks[event]) {
4187
- // console.log('webhook already registered');
4188
- // return false;
4189
- // }
4190
- // this._registeredWebhooks[event] = this[event](async _data=>await this._webhookQueue.add(async () => await axios({
4191
- // method: 'post',
4192
- // url,
4193
- // data: {
4194
- // ts: Date.now(),
4195
- // event,
4196
- // data:_data
4197
- // },
4198
- // ...requestConfig
4199
- // })));
4200
- // return this._registeredWebhooks[event];
4201
- // }
4202
- // console.log('Invalid lisetner', event);
4203
- // return false;
4204
- // }
4205
- _setupWebhooksOnListeners(events) {
4206
- return __awaiter(this, void 0, void 0, function* () {
4207
- if (events === "all")
4208
- events = Object.keys(events_2.SimpleListener).map(eventKey => events_2.SimpleListener[eventKey]);
4209
- if (!Array.isArray(events))
4210
- events = [events];
4211
- if (!this._registeredWebhookListeners)
4212
- this._registeredWebhookListeners = {};
4213
- if (!this._registeredWebhooks)
4214
- this._registeredWebhooks = {};
4215
- const validListeners = [];
4216
- events.map(event => {
4217
- if (!event.startsWith("on"))
4218
- event = `on${event}`;
4219
- if (this[event]) {
4220
- validListeners.push(event);
4221
- if (this._registeredWebhookListeners[event] === undefined) {
4222
- //set it up
4223
- this._registeredWebhookListeners[event] = this[event]((_data) => __awaiter(this, void 0, void 0, function* () {
4224
- return yield this._webhookQueue.add(() => __awaiter(this, void 0, void 0, function* () {
4225
- return yield Promise.all([
4226
- ...Object.keys(this._registeredWebhooks).map(webhookId => this._registeredWebhooks[webhookId]).filter(webhookEntry => webhookEntry.events.includes(event))
4227
- ].map(({ id, url, requestConfig }) => {
4228
- const whStart = (0, tools_1.now)();
4229
- return (0, axios_1.default)(Object.assign({ method: 'post', url, data: this.prepEventData(_data, event, { webhook_id: id }) }, requestConfig))
4230
- .then(({ status }) => {
4231
- const t = ((0, tools_1.now)() - whStart).toFixed(0);
4232
- logging_1.log.info("Client Webhook", event, status, t);
4233
- })
4234
- .catch(err => logging_1.log.error(`CLIENT WEBHOOK ERROR: `, url, err.message));
4235
- }));
4236
- }));
4237
- }), 10000);
4238
- }
4239
- }
4240
- });
4241
- return validListeners;
4242
- });
4243
- }
4244
- /**
4245
- * The client can now automatically handle webhooks. Use this method to register webhooks.
4246
- *
4247
- * @param url The webhook url
4248
- * @param events An array of [[SimpleListener]] enums or `all` (to register all possible listeners)
4249
- * @param requestConfig {} By default the request is a post request, however you can override that and many other options by sending this parameter. You can read more about this parameter here: https://github.com/axios/axios#request-config
4250
- * @param concurrency the amount of concurrent requests to be handled by the built in queue. Default is 5.
4251
- * @returns A webhook object. This will include a webhook ID and an array of all successfully registered Listeners.
4252
- */
4253
- registerWebhook(url, events, requestConfig = {}, concurrency = 5) {
4254
- return __awaiter(this, void 0, void 0, function* () {
4255
- if (!this._webhookQueue)
4256
- this._webhookQueue = new p_queue_1.default({ concurrency });
4257
- const validListeners = yield this._setupWebhooksOnListeners(events);
4258
- const id = (0, uuid_1.v4)();
4259
- if (validListeners.length) {
4260
- this._registeredWebhooks[id] = {
4261
- id,
4262
- ts: Date.now(),
4263
- url,
4264
- events: validListeners,
4265
- requestConfig
4266
- };
4267
- return this._registeredWebhooks[id];
4268
- }
4269
- console.log('Invalid listener(s)', events);
4270
- logging_1.log.warn('Invalid listener(s)', events);
4271
- return false;
4272
- });
4273
- }
4274
- prepEventData(data, event, extras) {
4275
- const sessionId = this.getSessionId();
4276
- return Object.assign({ ts: Date.now(), sessionId, id: (0, uuid_1.v4)(), event,
4277
- data }, extras);
4278
- }
4279
- getEventSignature(simpleListener) {
4280
- return `${simpleListener || '**'}.${this._createConfig.sessionId || 'session'}.${this._sessionInfo.INSTANCE_ID}`;
4281
- }
4282
- registerEv(simpleListener) {
4283
- return __awaiter(this, void 0, void 0, function* () {
4284
- if (this[simpleListener]) {
4285
- if (!this._registeredEvListeners)
4286
- this._registeredEvListeners = {};
4287
- if (this._registeredEvListeners[simpleListener]) {
4288
- console.log('Listener already registered');
4289
- logging_1.log.warn('Listener already registered');
4290
- return false;
4291
- }
4292
- this._registeredEvListeners[simpleListener] = yield this[simpleListener](data => events_1.ev.emit(this.getEventSignature(simpleListener), this.prepEventData(data, simpleListener)));
4293
- return true;
4294
- }
4295
- console.log('Invalid lisetner', simpleListener);
4296
- logging_1.log.warn('Invalid lisetner', simpleListener);
4297
- return false;
4298
- });
4299
- }
4300
- /**
4301
- * Every time this is called, it returns one less number. This is used to sort out queue priority.
4302
- */
4303
- tickPriority() {
4304
- this._prio = this._prio - 1;
4305
- return this._prio;
4306
- }
4307
- /**
4308
- * Get the INSTANCE_ID of the current session
4309
- */
4310
- getInstanceId() {
4311
- return this._sessionInfo.INSTANCE_ID;
4312
- }
4313
- /**
4314
- * Returns a new message collector for the chat which is related to the first parameter c
4315
- * @param c The Mesasge/Chat or Chat Id to base this message colletor on
4316
- * @param filter A function that consumes a [Message] and returns a boolean which determines whether or not the message shall be collected.
4317
- * @param options The options for the collector. For example, how long the collector shall run for, how many messages it should collect, how long between messages before timing out, etc.
4318
- */
4319
- createMessageCollector(c, filter, options) {
4320
- var _a;
4321
- const chatId = (((_a = c === null || c === void 0 ? void 0 : c.chat) === null || _a === void 0 ? void 0 : _a.id) || (c === null || c === void 0 ? void 0 : c.id) || c);
4322
- return new MessageCollector_1.MessageCollector(this.getSessionId(), this.getInstanceId(), chatId, filter, options, events_1.ev);
4323
- }
4324
- /**
4325
- * [FROM DISCORDJS]
4326
- * Similar to createMessageCollector but in promise form.
4327
- * Resolves with a collection of messages that pass the specified filter.
4328
- * @param c The Mesasge/Chat or Chat Id to base this message colletor on
4329
- * @param {CollectorFilter} filter The filter function to use
4330
- * @param {AwaitMessagesOptions} [options={}] Optional options to pass to the internal collector
4331
- * @returns {Promise<Collection<string, Message>>}
4332
- * @example
4333
- * ```javascript
4334
- * // Await !vote messages
4335
- * const filter = m => m.body.startsWith('!vote');
4336
- * // Errors: ['time'] treats ending because of the time limit as an error
4337
- * channel.awaitMessages(filter, { max: 4, time: 60000, errors: ['time'] })
4338
- * .then(collected => console.log(collected.size))
4339
- * .catch(collected => console.log(`After a minute, only ${collected.size} out of 4 voted.`));
4340
- * ```
4341
- */
4342
- awaitMessages(c, filter, options = {}) {
4343
- return new Promise((resolve, reject) => {
4344
- const collector = this.createMessageCollector(c, filter, options);
4345
- collector.once('end', (collection, reason) => {
4346
- if (options.errors && options.errors.includes(reason)) {
4347
- reject(collection);
4348
- }
4349
- else {
4350
- resolve(collection);
4351
- }
4352
- });
4353
- });
4354
- }
4355
- }
4356
- exports.Client = Client;
4357
- var puppeteer_config_2 = require("../config/puppeteer.config");
4358
- Object.defineProperty(exports, "useragent", { enumerable: true, get: function () { return puppeteer_config_2.useragent; } });