@another-trial/whatsapp-web.js 1.34.0 → 1.35.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.env.example +2 -2
  2. package/CODE_OF_CONDUCT.md +133 -133
  3. package/LICENSE +201 -201
  4. package/README.md +185 -185
  5. package/example.js +690 -690
  6. package/index.d.ts +2239 -2202
  7. package/index.js +35 -35
  8. package/package.json +59 -59
  9. package/shell.js +36 -36
  10. package/src/Client.js +2445 -2361
  11. package/src/authStrategies/BaseAuthStrategy.js +26 -26
  12. package/src/authStrategies/LocalAuth.js +58 -58
  13. package/src/authStrategies/NoAuth.js +11 -11
  14. package/src/authStrategies/RemoteAuth.js +210 -210
  15. package/src/factories/ChatFactory.js +21 -21
  16. package/src/factories/ContactFactory.js +15 -15
  17. package/src/structures/Base.js +21 -21
  18. package/src/structures/Broadcast.js +69 -69
  19. package/src/structures/BusinessContact.js +20 -20
  20. package/src/structures/Buttons.js +81 -81
  21. package/src/structures/Call.js +75 -75
  22. package/src/structures/Channel.js +382 -382
  23. package/src/structures/Chat.js +329 -299
  24. package/src/structures/ClientInfo.js +70 -70
  25. package/src/structures/Contact.js +208 -208
  26. package/src/structures/GroupChat.js +485 -485
  27. package/src/structures/GroupNotification.js +104 -104
  28. package/src/structures/Label.js +49 -49
  29. package/src/structures/List.js +79 -79
  30. package/src/structures/Location.js +61 -61
  31. package/src/structures/Message.js +754 -747
  32. package/src/structures/MessageMedia.js +111 -111
  33. package/src/structures/Order.js +51 -51
  34. package/src/structures/Payment.js +79 -79
  35. package/src/structures/Poll.js +44 -44
  36. package/src/structures/PollVote.js +75 -75
  37. package/src/structures/PrivateChat.js +12 -12
  38. package/src/structures/PrivateContact.js +12 -12
  39. package/src/structures/Product.js +67 -67
  40. package/src/structures/ProductMetadata.js +24 -24
  41. package/src/structures/Reaction.js +68 -68
  42. package/src/structures/ScheduledEvent.js +71 -71
  43. package/src/structures/index.js +27 -27
  44. package/src/util/Constants.js +183 -183
  45. package/src/util/Injected/AuthStore/AuthStore.js +16 -16
  46. package/src/util/Injected/AuthStore/LegacyAuthStore.js +21 -21
  47. package/src/util/Injected/LegacyStore.js +145 -145
  48. package/src/util/Injected/Store.js +250 -231
  49. package/src/util/Injected/Utils.js +1156 -1169
  50. package/src/util/InterfaceController.js +126 -126
  51. package/src/util/Puppeteer.js +23 -23
  52. package/src/util/Util.js +186 -186
  53. package/src/webCache/LocalWebCache.js +40 -40
  54. package/src/webCache/RemoteWebCache.js +39 -39
  55. package/src/webCache/WebCache.js +13 -13
  56. package/src/webCache/WebCacheFactory.js +19 -19
@@ -1,1169 +1,1156 @@
1
- 'use strict';
2
-
3
- exports.LoadUtils = () => {
4
- window.WWebJS = {};
5
-
6
- window.WWebJS.forwardMessage = async (chatId, msgId) => {
7
- const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
8
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
9
- return window.Store.ForwardUtils.forwardMessages(chat, [msg], true, true);
10
- };
11
-
12
- window.WWebJS.sendSeen = async (chatId) => {
13
- const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
14
- if (chat) {
15
- window.Store.WAWebStreamModel.Stream.markAvailable();
16
- await window.Store.SendSeen.sendSeen(chat);
17
- return true;
18
- }
19
- return false;
20
- };
21
-
22
- window.WWebJS.sendMessage = async (chat, content, options = {}) => {
23
- const isChannel = window.Store.ChatGetters.getIsNewsletter(chat);
24
-
25
- let mediaOptions = {};
26
- if (options.media) {
27
- mediaOptions = options.sendMediaAsSticker && !isChannel
28
- ? await window.WWebJS.processStickerData(options.media)
29
- : await window.WWebJS.processMediaData(options.media, {
30
- forceSticker: options.sendMediaAsSticker,
31
- forceGif: options.sendVideoAsGif,
32
- forceVoice: options.sendAudioAsVoice,
33
- forceDocument: options.sendMediaAsDocument,
34
- forceMediaHd: options.sendMediaAsHd,
35
- sendToChannel: isChannel
36
- });
37
- mediaOptions.caption = options.caption;
38
- content = options.sendMediaAsSticker ? undefined : mediaOptions.preview;
39
- mediaOptions.isViewOnce = options.isViewOnce;
40
- delete options.media;
41
- delete options.sendMediaAsSticker;
42
- }
43
-
44
- let quotedMsgOptions = {};
45
- if (options.quotedMessageId) {
46
- let quotedMessage = window.Store.Msg.get(options.quotedMessageId);
47
- !quotedMessage && (quotedMessage = (await window.Store.Msg.getMessagesById([options.quotedMessageId]))?.messages?.[0]);
48
- if (quotedMessage) {
49
-
50
- const canReply = window.Store.ReplyUtils
51
- ? window.Store.ReplyUtils.canReplyMsg(quotedMessage.unsafe())
52
- : quotedMessage.canReply();
53
-
54
- if (canReply) {
55
- quotedMsgOptions = quotedMessage.msgContextInfo(chat);
56
- }
57
- } else {
58
- if (!options.ignoreQuoteErrors) {
59
- throw new Error('Could not get the quoted message.');
60
- }
61
- }
62
-
63
- delete options.ignoreQuoteErrors;
64
- delete options.quotedMessageId;
65
- }
66
-
67
- if (options.mentionedJidList) {
68
- options.mentionedJidList = await Promise.all(
69
- options.mentionedJidList.map(async (id) => {
70
- const wid = window.Store.WidFactory.createWid(id);
71
- if (await window.Store.QueryExist(wid)) {
72
- return wid;
73
- }
74
- })
75
- );
76
- options.mentionedJidList = options.mentionedJidList.filter(Boolean);
77
- }
78
-
79
- if (options.groupMentions) {
80
- options.groupMentions = options.groupMentions.map((e) => ({
81
- groupSubject: e.subject,
82
- groupJid: window.Store.WidFactory.createWid(e.id)
83
- }));
84
- }
85
-
86
- let locationOptions = {};
87
- if (options.location) {
88
- let { latitude, longitude, description, url } = options.location;
89
- url = window.Store.Validators.findLink(url)?.href;
90
- url && !description && (description = url);
91
- locationOptions = {
92
- type: 'location',
93
- loc: description,
94
- lat: latitude,
95
- lng: longitude,
96
- clientUrl: url
97
- };
98
- delete options.location;
99
- }
100
-
101
- let _pollOptions = {};
102
- if (options.poll) {
103
- const { pollName, pollOptions } = options.poll;
104
- const { allowMultipleAnswers, messageSecret } = options.poll.options;
105
- _pollOptions = {
106
- kind: 'pollCreation',
107
- type: 'poll_creation',
108
- pollName: pollName,
109
- pollOptions: pollOptions,
110
- pollSelectableOptionsCount: allowMultipleAnswers ? 0 : 1,
111
- messageSecret:
112
- Array.isArray(messageSecret) && messageSecret.length === 32
113
- ? new Uint8Array(messageSecret)
114
- : window.crypto.getRandomValues(new Uint8Array(32))
115
- };
116
- delete options.poll;
117
- }
118
-
119
- let eventOptions = {};
120
- if (options.event) {
121
- const { name, startTimeTs, eventSendOptions } = options.event;
122
- const { messageSecret } = eventSendOptions;
123
- eventOptions = {
124
- type: 'event_creation',
125
- eventName: name,
126
- eventDescription: eventSendOptions.description,
127
- eventStartTime: startTimeTs,
128
- eventEndTime: eventSendOptions.endTimeTs,
129
- eventLocation: eventSendOptions.location && {
130
- degreesLatitude: 0,
131
- degreesLongitude: 0,
132
- name: eventSendOptions.location
133
- },
134
- eventJoinLink: await window.Store.ScheduledEventMsgUtils.createEventCallLink(
135
- startTimeTs,
136
- eventSendOptions.callType
137
- ),
138
- isEventCanceled: eventSendOptions.isEventCanceled,
139
- messageSecret:
140
- Array.isArray(messageSecret) && messageSecret.length === 32
141
- ? new Uint8Array(messageSecret)
142
- : window.crypto.getRandomValues(new Uint8Array(32)),
143
- };
144
- delete options.event;
145
- }
146
-
147
- let vcardOptions = {};
148
- if (options.contactCard) {
149
- let contact = window.Store.Contact.get(options.contactCard);
150
- vcardOptions = {
151
- body: window.Store.VCard.vcardFromContactModel(contact).vcard,
152
- type: 'vcard',
153
- vcardFormattedName: contact.formattedName
154
- };
155
- delete options.contactCard;
156
- } else if (options.contactCardList) {
157
- let contacts = options.contactCardList.map(c => window.Store.Contact.get(c));
158
- let vcards = contacts.map(c => window.Store.VCard.vcardFromContactModel(c));
159
- vcardOptions = {
160
- type: 'multi_vcard',
161
- vcardList: vcards,
162
- body: null
163
- };
164
- delete options.contactCardList;
165
- } else if (options.parseVCards && typeof (content) === 'string' && content.startsWith('BEGIN:VCARD')) {
166
- delete options.parseVCards;
167
- delete options.linkPreview;
168
- try {
169
- const parsed = window.Store.VCard.parseVcard(content);
170
- if (parsed) {
171
- vcardOptions = {
172
- type: 'vcard',
173
- vcardFormattedName: window.Store.VCard.vcardGetNameFromParsed(parsed)
174
- };
175
- }
176
- } catch (_) {
177
- // not a vcard
178
- }
179
- }
180
-
181
- if (options.linkPreview) {
182
- delete options.linkPreview;
183
- const link = window.Store.Validators.findLink(content);
184
- if (link) {
185
- let preview = await window.Store.LinkPreview.getLinkPreview(link);
186
- if (preview && preview.data) {
187
- preview = preview.data;
188
- preview.preview = true;
189
- preview.subtype = 'url';
190
- options = {...options, ...preview};
191
- }
192
- }
193
- }
194
-
195
- let buttonOptions = {};
196
- if (options.buttons) {
197
- let caption;
198
- if (options.buttons.type === 'chat') {
199
- content = options.buttons.body;
200
- caption = content;
201
- } else {
202
- caption = options.caption ? options.caption : ' '; //Caption can't be empty
203
- }
204
- buttonOptions = {
205
- productHeaderImageRejected: false,
206
- isFromTemplate: false,
207
- isDynamicReplyButtonsMsg: true,
208
- title: options.buttons.title ? options.buttons.title : undefined,
209
- footer: options.buttons.footer ? options.buttons.footer : undefined,
210
- dynamicReplyButtons: options.buttons.buttons,
211
- replyButtons: options.buttons.buttons,
212
- caption: caption
213
- };
214
- delete options.buttons;
215
- }
216
-
217
- let listOptions = {};
218
- if (options.list) {
219
- if (window.Store.Conn.platform === 'smba' || window.Store.Conn.platform === 'smbi') {
220
- throw '[LT01] Whatsapp business can\'t send this yet';
221
- }
222
- listOptions = {
223
- type: 'list',
224
- footer: options.list.footer,
225
- list: {
226
- ...options.list,
227
- listType: 1
228
- },
229
- body: options.list.description
230
- };
231
- delete options.list;
232
- delete listOptions.list.footer;
233
- }
234
-
235
- const botOptions = {};
236
- if (options.invokedBotWid) {
237
- botOptions.messageSecret = window.crypto.getRandomValues(new Uint8Array(32));
238
- botOptions.botMessageSecret = await window.Store.BotSecret.genBotMsgSecretFromMsgSecret(botOptions.messageSecret);
239
- botOptions.invokedBotWid = window.Store.WidFactory.createWid(options.invokedBotWid);
240
- botOptions.botPersonaId = window.Store.BotProfiles.BotProfileCollection.get(options.invokedBotWid).personaId;
241
- delete options.invokedBotWid;
242
- }
243
-
244
- const lidUser = window.Store.User.getMaybeMeLidUser();
245
- const meUser = window.Store.User.getMaybeMePnUser();
246
- const newId = await window.Store.MsgKey.newId();
247
- let from = chat.id.isLid() ? lidUser : meUser;
248
- let participant;
249
-
250
- if (typeof chat.id?.isGroup === 'function' && chat.id.isGroup()) {
251
- from = chat.groupMetadata && chat.groupMetadata.isLidAddressingMode ? lidUser : meUser;
252
- participant = window.Store.WidFactory.asUserWidOrThrow(from);
253
- }
254
-
255
- const newMsgKey = new window.Store.MsgKey({
256
- from: from,
257
- to: chat.id,
258
- id: newId,
259
- participant: participant,
260
- selfDir: 'out',
261
- });
262
-
263
- const extraOptions = options.extraOptions || {};
264
- delete options.extraOptions;
265
-
266
- const ephemeralFields = window.Store.EphemeralFields.getEphemeralFields(chat);
267
-
268
- const message = {
269
- ...options,
270
- id: newMsgKey,
271
- ack: 0,
272
- body: content,
273
- from: meUser,
274
- to: chat.id,
275
- local: true,
276
- self: 'out',
277
- t: parseInt(new Date().getTime() / 1000),
278
- isNewMsg: true,
279
- type: 'chat',
280
- ...ephemeralFields,
281
- ...mediaOptions,
282
- ...(mediaOptions.toJSON ? mediaOptions.toJSON() : {}),
283
- ...quotedMsgOptions,
284
- ...locationOptions,
285
- ..._pollOptions,
286
- ...eventOptions,
287
- ...vcardOptions,
288
- ...buttonOptions,
289
- ...listOptions,
290
- ...botOptions,
291
- ...extraOptions
292
- };
293
-
294
- // Bot's won't reply if canonicalUrl is set (linking)
295
- if (botOptions) {
296
- delete message.canonicalUrl;
297
- }
298
-
299
- if (isChannel) {
300
- const msg = new window.Store.Msg.modelClass(message);
301
- const msgDataFromMsgModel = window.Store.SendChannelMessage.msgDataFromMsgModel(msg);
302
- const isMedia = Object.keys(mediaOptions).length > 0;
303
- await window.Store.SendChannelMessage.addNewsletterMsgsRecords([msgDataFromMsgModel]);
304
- chat.msgs.add(msg);
305
- chat.t = msg.t;
306
-
307
- const sendChannelMsgResponse = await window.Store.SendChannelMessage.sendNewsletterMessageJob({
308
- msg: msg,
309
- type: message.type === 'chat' ? 'text' : isMedia ? 'media' : 'pollCreation',
310
- newsletterJid: chat.id.toJid(),
311
- ...(isMedia
312
- ? {
313
- mediaMetadata: msg.avParams(),
314
- mediaHandle: isMedia ? mediaOptions.mediaHandle : null,
315
- }
316
- : {}
317
- )
318
- });
319
-
320
- if (sendChannelMsgResponse.success) {
321
- msg.t = sendChannelMsgResponse.ack.t;
322
- msg.serverId = sendChannelMsgResponse.serverId;
323
- }
324
- msg.updateAck(1, true);
325
- await window.Store.SendChannelMessage.updateNewsletterMsgRecord(msg);
326
- return msg;
327
- }
328
-
329
- const [msgPromise, sendMsgResultPromise] = window.Store.SendMessage.addAndSendMsgToChat(chat, message);
330
- await msgPromise;
331
-
332
- if (options.waitUntilMsgSent) await sendMsgResultPromise;
333
-
334
- return window.Store.Msg.get(newMsgKey._serialized);
335
- };
336
-
337
- window.WWebJS.editMessage = async (msg, content, options = {}) => {
338
- const extraOptions = options.extraOptions || {};
339
- delete options.extraOptions;
340
-
341
- if (options.mentionedJidList) {
342
- options.mentionedJidList = await Promise.all(
343
- options.mentionedJidList.map(async (id) => {
344
- const wid = window.Store.WidFactory.createWid(id);
345
- if (await window.Store.QueryExist(wid)) {
346
- return wid;
347
- }
348
- })
349
- );
350
- options.mentionedJidList = options.mentionedJidList.filter(Boolean);
351
- }
352
-
353
- if (options.groupMentions) {
354
- options.groupMentions = options.groupMentions.map((e) => ({
355
- groupSubject: e.subject,
356
- groupJid: window.Store.WidFactory.createWid(e.id)
357
- }));
358
- }
359
-
360
- if (options.linkPreview) {
361
- delete options.linkPreview;
362
- const link = window.Store.Validators.findLink(content);
363
- if (link) {
364
- const preview = await window.Store.LinkPreview.getLinkPreview(link);
365
- preview.preview = true;
366
- preview.subtype = 'url';
367
- options = { ...options, ...preview };
368
- }
369
- }
370
-
371
-
372
- const internalOptions = {
373
- ...options,
374
- ...extraOptions
375
- };
376
-
377
- await window.Store.EditMessage.sendMessageEdit(msg, content, internalOptions);
378
- return window.Store.Msg.get(msg.id._serialized);
379
- };
380
-
381
- window.WWebJS.toStickerData = async (mediaInfo) => {
382
- if (mediaInfo.mimetype == 'image/webp') return mediaInfo;
383
-
384
- const file = window.WWebJS.mediaInfoToFile(mediaInfo);
385
- const webpSticker = await window.Store.StickerTools.toWebpSticker(file);
386
- const webpBuffer = await webpSticker.arrayBuffer();
387
- const data = window.WWebJS.arrayBufferToBase64(webpBuffer);
388
-
389
- return {
390
- mimetype: 'image/webp',
391
- data
392
- };
393
- };
394
-
395
- window.WWebJS.processStickerData = async (mediaInfo) => {
396
- if (mediaInfo.mimetype !== 'image/webp') throw new Error('Invalid media type');
397
-
398
- const file = window.WWebJS.mediaInfoToFile(mediaInfo);
399
- let filehash = await window.WWebJS.getFileHash(file);
400
- let mediaKey = await window.WWebJS.generateHash(32);
401
-
402
- const controller = new AbortController();
403
- const uploadedInfo = await window.Store.UploadUtils.encryptAndUpload({
404
- blob: file,
405
- type: 'sticker',
406
- signal: controller.signal,
407
- mediaKey
408
- });
409
-
410
- const stickerInfo = {
411
- ...uploadedInfo,
412
- clientUrl: uploadedInfo.url,
413
- deprecatedMms3Url: uploadedInfo.url,
414
- uploadhash: uploadedInfo.encFilehash,
415
- size: file.size,
416
- type: 'sticker',
417
- filehash
418
- };
419
-
420
- return stickerInfo;
421
- };
422
-
423
- window.WWebJS.processMediaData = async (mediaInfo, { forceSticker, forceGif, forceVoice, forceDocument, forceMediaHd, sendToChannel }) => {
424
- const file = window.WWebJS.mediaInfoToFile(mediaInfo);
425
- const opaqueData = await window.Store.OpaqueData.createFromData(file, file.type);
426
- const mediaParams = {
427
- asSticker: forceSticker,
428
- asGif: forceGif,
429
- isPtt: forceVoice,
430
- asDocument: forceDocument
431
- };
432
-
433
- if (forceMediaHd && file.type.indexOf('image/') === 0) {
434
- mediaParams.maxDimension = 2560;
435
- }
436
-
437
- const mediaPrep = window.Store.MediaPrep.prepRawMedia(opaqueData, mediaParams);
438
- const mediaData = await mediaPrep.waitForPrep();
439
- const mediaObject = window.Store.MediaObject.getOrCreateMediaObject(mediaData.filehash);
440
- const mediaType = window.Store.MediaTypes.msgToMediaType({
441
- type: mediaData.type,
442
- isGif: mediaData.isGif,
443
- isNewsletter: sendToChannel,
444
- });
445
-
446
- if (forceVoice && mediaData.type === 'ptt') {
447
- const waveform = mediaObject.contentInfo.waveform;
448
- mediaData.waveform =
449
- waveform || await window.WWebJS.generateWaveform(file);
450
- }
451
-
452
- if (!(mediaData.mediaBlob instanceof window.Store.OpaqueData)) {
453
- mediaData.mediaBlob = await window.Store.OpaqueData.createFromData(
454
- mediaData.mediaBlob,
455
- mediaData.mediaBlob.type
456
- );
457
- }
458
-
459
- mediaData.renderableUrl = mediaData.mediaBlob.url();
460
- mediaObject.consolidate(mediaData.toJSON());
461
- mediaData.mediaBlob.autorelease();
462
-
463
- const dataToUpload = {
464
- mimetype: mediaData.mimetype,
465
- mediaObject,
466
- mediaType,
467
- ...(sendToChannel ? { calculateToken: window.Store.SendChannelMessage.getRandomFilehash } : {})
468
- };
469
-
470
- const uploadedMedia = !sendToChannel
471
- ? await window.Store.MediaUpload.uploadMedia(dataToUpload)
472
- : await window.Store.MediaUpload.uploadUnencryptedMedia(dataToUpload);
473
-
474
- const mediaEntry = uploadedMedia.mediaEntry;
475
- if (!mediaEntry) {
476
- throw new Error('upload failed: media entry was not created');
477
- }
478
-
479
- mediaData.set({
480
- clientUrl: mediaEntry.mmsUrl,
481
- deprecatedMms3Url: mediaEntry.deprecatedMms3Url,
482
- directPath: mediaEntry.directPath,
483
- mediaKey: mediaEntry.mediaKey,
484
- mediaKeyTimestamp: mediaEntry.mediaKeyTimestamp,
485
- filehash: mediaObject.filehash,
486
- encFilehash: mediaEntry.encFilehash,
487
- uploadhash: mediaEntry.uploadHash,
488
- size: mediaObject.size,
489
- streamingSidecar: mediaEntry.sidecar,
490
- firstFrameSidecar: mediaEntry.firstFrameSidecar,
491
- mediaHandle: sendToChannel ? mediaEntry.handle : null,
492
- });
493
-
494
- return mediaData;
495
- };
496
-
497
- window.WWebJS.getMessageModel = (message) => {
498
- const msg = message.serialize();
499
-
500
- msg.isEphemeral = message.isEphemeral;
501
- msg.isStatusV3 = message.isStatusV3;
502
- msg.links = (window.Store.Validators.findLinks(message.mediaObject ? message.caption : message.body)).map((link) => ({
503
- link: link.href,
504
- isSuspicious: Boolean(link.suspiciousCharacters && link.suspiciousCharacters.size)
505
- }));
506
-
507
- if (msg.buttons) {
508
- msg.buttons = msg.buttons.serialize();
509
- }
510
- if (msg.dynamicReplyButtons) {
511
- msg.dynamicReplyButtons = JSON.parse(JSON.stringify(msg.dynamicReplyButtons));
512
- }
513
- if (msg.replyButtons) {
514
- msg.replyButtons = JSON.parse(JSON.stringify(msg.replyButtons));
515
- }
516
-
517
- if (typeof msg.id.remote === 'object') {
518
- msg.id = Object.assign({}, msg.id, { remote: msg.id.remote._serialized });
519
- }
520
-
521
- delete msg.pendingAckUpdate;
522
-
523
- return msg;
524
- };
525
-
526
- window.WWebJS.getChat = async (chatId, { getAsModel = true } = {}) => {
527
- const isChannel = /@\w*newsletter\b/.test(chatId);
528
- const chatWid = window.Store.WidFactory.createWid(chatId);
529
- let chat;
530
-
531
- if (isChannel) {
532
- try {
533
- chat = window.Store.NewsletterCollection.get(chatId);
534
- if (!chat) {
535
- await window.Store.ChannelUtils.loadNewsletterPreviewChat(chatId);
536
- chat = await window.Store.NewsletterCollection.find(chatWid);
537
- }
538
- } catch (err) {
539
- chat = null;
540
- }
541
- } else {
542
- chat = window.Store.Chat.get(chatWid) || (await window.Store.FindOrCreateChat.findOrCreateLatestChat(chatWid))?.chat;
543
- }
544
-
545
- return getAsModel && chat
546
- ? await window.WWebJS.getChatModel(chat, { isChannel: isChannel })
547
- : chat;
548
- };
549
-
550
- window.WWebJS.getChannelMetadata = async (inviteCode) => {
551
- const response =
552
- await window.Store.ChannelUtils.queryNewsletterMetadataByInviteCode(
553
- inviteCode,
554
- window.Store.ChannelUtils.getRoleByIdentifier(inviteCode)
555
- );
556
-
557
- const picUrl = response.newsletterPictureMetadataMixin?.picture[0]?.queryPictureDirectPathOrEmptyResponseMixinGroup.value.directPath;
558
-
559
- return {
560
- id: response.idJid,
561
- createdAtTs: response.newsletterCreationTimeMetadataMixin.creationTimeValue,
562
- titleMetadata: {
563
- title: response.newsletterNameMetadataMixin.nameElementValue,
564
- updatedAtTs: response.newsletterNameMetadataMixin.nameUpdateTime
565
- },
566
- descriptionMetadata: {
567
- description: response.newsletterDescriptionMetadataMixin.descriptionQueryDescriptionResponseMixin.elementValue,
568
- updatedAtTs: response.newsletterDescriptionMetadataMixin.descriptionQueryDescriptionResponseMixin.updateTime
569
- },
570
- inviteLink: `https://whatsapp.com/channel/${response.newsletterInviteLinkMetadataMixin.inviteCode}`,
571
- membershipType: window.Store.ChannelUtils.getRoleByIdentifier(inviteCode),
572
- stateType: response.newsletterStateMetadataMixin.stateType,
573
- pictureUrl: picUrl ? `https://pps.whatsapp.net${picUrl}` : null,
574
- subscribersCount: response.newsletterSubscribersMetadataMixin.subscribersCount,
575
- isVerified: response.newsletterVerificationMetadataMixin.verificationState === 'verified'
576
- };
577
- };
578
-
579
- window.WWebJS.getChats = async () => {
580
- const chats = window.Store.Chat.getModelsArray();
581
- const chatPromises = chats.map(chat => window.WWebJS.getChatModel(chat));
582
- return await Promise.all(chatPromises);
583
- };
584
-
585
- window.WWebJS.getChannels = async () => {
586
- const channels = window.Store.NewsletterCollection.getModelsArray();
587
- const channelPromises = channels?.map((channel) => window.WWebJS.getChatModel(channel, { isChannel: true }));
588
- return await Promise.all(channelPromises);
589
- };
590
-
591
- window.WWebJS.getChatModel = async (chat, { isChannel = false } = {}) => {
592
- if (!chat) return null;
593
-
594
- const model = chat.serialize();
595
- model.isGroup = false;
596
- model.isMuted = chat.mute?.expiration !== 0;
597
- if (isChannel) {
598
- model.isChannel = window.Store.ChatGetters.getIsNewsletter(chat);
599
- } else {
600
- model.formattedTitle = chat.formattedTitle;
601
- }
602
-
603
- if (chat.groupMetadata) {
604
- model.isGroup = true;
605
- const chatWid = window.Store.WidFactory.createWid(chat.id._serialized);
606
- await window.Store.GroupMetadata.update(chatWid);
607
- chat.groupMetadata.participants._models
608
- .filter(x => x.id?._serialized?.endsWith('@lid'))
609
- .forEach(x => x.contact?.phoneNumber && (x.id = x.contact.phoneNumber));
610
- model.groupMetadata = chat.groupMetadata.serialize();
611
- model.isReadOnly = chat.groupMetadata.announce;
612
- }
613
-
614
- if (chat.newsletterMetadata) {
615
- await window.Store.NewsletterMetadataCollection.update(chat.id);
616
- model.channelMetadata = chat.newsletterMetadata.serialize();
617
- model.channelMetadata.createdAtTs = chat.newsletterMetadata.creationTime;
618
- }
619
-
620
- model.lastMessage = null;
621
- if (model.msgs && model.msgs.length) {
622
- const lastMessage = chat.lastReceivedKey
623
- ? window.Store.Msg.get(chat.lastReceivedKey._serialized) || (await window.Store.Msg.getMessagesById([chat.lastReceivedKey._serialized]))?.messages?.[0]
624
- : null;
625
- lastMessage && (model.lastMessage = window.WWebJS.getMessageModel(lastMessage));
626
- }
627
-
628
- delete model.msgs;
629
- delete model.msgUnsyncedButtonReplyMsgs;
630
- delete model.unsyncedButtonReplies;
631
-
632
- return model;
633
- };
634
-
635
- window.WWebJS.getContactModel = contact => {
636
- let res = contact.serialize();
637
- res.isBusiness = contact.isBusiness === undefined ? false : contact.isBusiness;
638
-
639
- if (contact.businessProfile) {
640
- res.businessProfile = contact.businessProfile.serialize();
641
- }
642
-
643
- res.isMe = window.Store.ContactMethods.getIsMe(contact);
644
- res.isUser = window.Store.ContactMethods.getIsUser(contact);
645
- res.isGroup = window.Store.ContactMethods.getIsGroup(contact);
646
- res.isWAContact = window.Store.ContactMethods.getIsWAContact(contact);
647
- res.isMyContact = window.Store.ContactMethods.getIsMyContact(contact);
648
- res.isBlocked = contact.isContactBlocked;
649
- res.userid = window.Store.ContactMethods.getUserid(contact);
650
- res.isEnterprise = window.Store.ContactMethods.getIsEnterprise(contact);
651
- res.verifiedName = window.Store.ContactMethods.getVerifiedName(contact);
652
- res.verifiedLevel = window.Store.ContactMethods.getVerifiedLevel(contact);
653
- res.statusMute = window.Store.ContactMethods.getStatusMute(contact);
654
- res.name = window.Store.ContactMethods.getName(contact);
655
- res.shortName = window.Store.ContactMethods.getShortName(contact);
656
- res.pushname = window.Store.ContactMethods.getPushname(contact);
657
-
658
- return res;
659
- };
660
-
661
- window.WWebJS.getContact = async contactId => {
662
- const wid = window.Store.WidFactory.createWid(contactId);
663
- let contact = await window.Store.Contact.find(wid);
664
- if (contact.id._serialized.endsWith('@lid')) {
665
- contact.id = contact.phoneNumber;
666
- }
667
- const bizProfile = await window.Store.BusinessProfile.fetchBizProfile(wid);
668
- bizProfile.profileOptions && (contact.businessProfile = bizProfile);
669
- return window.WWebJS.getContactModel(contact);
670
- };
671
-
672
- window.WWebJS.getContacts = () => {
673
- const contacts = window.Store.Contact.getModelsArray();
674
- return contacts.map(contact => window.WWebJS.getContactModel(contact));
675
- };
676
-
677
- window.WWebJS.mediaInfoToFile = ({ data, mimetype, filename }) => {
678
- const binaryData = window.atob(data);
679
-
680
- const buffer = new ArrayBuffer(binaryData.length);
681
- const view = new Uint8Array(buffer);
682
- for (let i = 0; i < binaryData.length; i++) {
683
- view[i] = binaryData.charCodeAt(i);
684
- }
685
-
686
- const blob = new Blob([buffer], { type: mimetype });
687
- return new File([blob], filename, {
688
- type: mimetype,
689
- lastModified: Date.now()
690
- });
691
- };
692
-
693
- window.WWebJS.arrayBufferToBase64 = (arrayBuffer) => {
694
- let binary = '';
695
- const bytes = new Uint8Array(arrayBuffer);
696
- const len = bytes.byteLength;
697
- for (let i = 0; i < len; i++) {
698
- binary += String.fromCharCode(bytes[i]);
699
- }
700
- return window.btoa(binary);
701
- };
702
-
703
- window.WWebJS.arrayBufferToBase64Async = (arrayBuffer) =>
704
- new Promise((resolve, reject) => {
705
- const blob = new Blob([arrayBuffer], {
706
- type: 'application/octet-stream',
707
- });
708
- const fileReader = new FileReader();
709
- fileReader.onload = () => {
710
- const [, data] = fileReader.result.split(',');
711
- resolve(data);
712
- };
713
- fileReader.onerror = (e) => reject(e);
714
- fileReader.readAsDataURL(blob);
715
- });
716
-
717
- window.WWebJS.getFileHash = async (data) => {
718
- let buffer = await data.arrayBuffer();
719
- const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
720
- return btoa(String.fromCharCode(...new Uint8Array(hashBuffer)));
721
- };
722
-
723
- window.WWebJS.generateHash = async (length) => {
724
- var result = '';
725
- var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
726
- var charactersLength = characters.length;
727
- for (var i = 0; i < length; i++) {
728
- result += characters.charAt(Math.floor(Math.random() * charactersLength));
729
- }
730
- return result;
731
- };
732
-
733
- window.WWebJS.generateWaveform = async (audioFile) => {
734
- try {
735
- const audioData = await audioFile.arrayBuffer();
736
- const audioContext = new AudioContext();
737
- const audioBuffer = await audioContext.decodeAudioData(audioData);
738
-
739
- const rawData = audioBuffer.getChannelData(0);
740
- const samples = 64;
741
- const blockSize = Math.floor(rawData.length / samples);
742
- const filteredData = [];
743
- for (let i = 0; i < samples; i++) {
744
- const blockStart = blockSize * i;
745
- let sum = 0;
746
- for (let j = 0; j < blockSize; j++) {
747
- sum = sum + Math.abs(rawData[blockStart + j]);
748
- }
749
- filteredData.push(sum / blockSize);
750
- }
751
-
752
- const multiplier = Math.pow(Math.max(...filteredData), -1);
753
- const normalizedData = filteredData.map((n) => n * multiplier);
754
-
755
- const waveform = new Uint8Array(
756
- normalizedData.map((n) => Math.floor(100 * n))
757
- );
758
-
759
- return waveform;
760
- } catch (e) {
761
- return undefined;
762
- }
763
- };
764
-
765
- window.WWebJS.sendClearChat = async (chatId) => {
766
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
767
- if (chat !== undefined) {
768
- await window.Store.SendClear.sendClear(chat, false);
769
- return true;
770
- }
771
- return false;
772
- };
773
-
774
- window.WWebJS.sendDeleteChat = async (chatId) => {
775
- let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
776
- if (chat !== undefined) {
777
- await window.Store.SendDelete.sendDelete(chat);
778
- return true;
779
- }
780
- return false;
781
- };
782
-
783
- window.WWebJS.sendChatstate = async (state, chatId) => {
784
- chatId = window.Store.WidFactory.createWid(chatId);
785
-
786
- switch (state) {
787
- case 'typing':
788
- await window.Store.ChatState.sendChatStateComposing(chatId);
789
- break;
790
- case 'recording':
791
- await window.Store.ChatState.sendChatStateRecording(chatId);
792
- break;
793
- case 'stop':
794
- await window.Store.ChatState.sendChatStatePaused(chatId);
795
- break;
796
- default:
797
- throw 'Invalid chatstate';
798
- }
799
-
800
- return true;
801
- };
802
-
803
- window.WWebJS.getLabelModel = label => {
804
- let res = label.serialize();
805
- res.hexColor = label.hexColor;
806
-
807
- return res;
808
- };
809
-
810
- window.WWebJS.getLabels = () => {
811
- const labels = window.Store.Label.getModelsArray();
812
- return labels.map(label => window.WWebJS.getLabelModel(label));
813
- };
814
-
815
- window.WWebJS.getLabel = (labelId) => {
816
- const label = window.Store.Label.get(labelId);
817
- return window.WWebJS.getLabelModel(label);
818
- };
819
-
820
- window.WWebJS.getChatLabels = async (chatId) => {
821
- const chat = await window.WWebJS.getChat(chatId);
822
- return (chat.labels || []).map(id => window.WWebJS.getLabel(id));
823
- };
824
-
825
- window.WWebJS.getOrderDetail = async (orderId, token, chatId) => {
826
- const chatWid = window.Store.WidFactory.createWid(chatId);
827
- return window.Store.QueryOrder.queryOrder(chatWid, orderId, 80, 80, token);
828
- };
829
-
830
- window.WWebJS.getProductMetadata = async (productId) => {
831
- let sellerId = window.Store.Conn.wid;
832
- let product = await window.Store.QueryProduct.queryProduct(sellerId, productId);
833
- if (product && product.data) {
834
- return product.data;
835
- }
836
-
837
- return undefined;
838
- };
839
-
840
- window.WWebJS.rejectCall = async (peerJid, id) => {
841
- peerJid = peerJid.split('@')[0] + '@s.whatsapp.net';
842
- let userId = window.Store.User.getMaybeMePnUser().user + '@s.whatsapp.net';
843
- const stanza = window.Store.SocketWap.wap('call', {
844
- id: window.Store.SocketWap.generateId(),
845
- from: window.Store.SocketWap.USER_JID(userId),
846
- to: window.Store.SocketWap.USER_JID(peerJid),
847
- }, [
848
- window.Store.SocketWap.wap('reject', {
849
- 'call-id': id,
850
- 'call-creator': window.Store.SocketWap.USER_JID(peerJid),
851
- count: '0',
852
- })
853
- ]);
854
- await window.Store.Socket.deprecatedCastStanza(stanza);
855
- };
856
-
857
- window.WWebJS.cropAndResizeImage = async (media, options = {}) => {
858
- if (!media.mimetype.includes('image'))
859
- throw new Error('Media is not an image');
860
-
861
- if (options.mimetype && !options.mimetype.includes('image'))
862
- delete options.mimetype;
863
-
864
- options = Object.assign({ size: 640, mimetype: media.mimetype, quality: .75, asDataUrl: false }, options);
865
-
866
- const img = await new Promise ((resolve, reject) => {
867
- const img = new Image();
868
- img.onload = () => resolve(img);
869
- img.onerror = reject;
870
- img.src = `data:${media.mimetype};base64,${media.data}`;
871
- });
872
-
873
- const sl = Math.min(img.width, img.height);
874
- const sx = Math.floor((img.width - sl) / 2);
875
- const sy = Math.floor((img.height - sl) / 2);
876
-
877
- const canvas = document.createElement('canvas');
878
- canvas.width = options.size;
879
- canvas.height = options.size;
880
-
881
- const ctx = canvas.getContext('2d');
882
- ctx.drawImage(img, sx, sy, sl, sl, 0, 0, options.size, options.size);
883
-
884
- const dataUrl = canvas.toDataURL(options.mimetype, options.quality);
885
-
886
- if (options.asDataUrl)
887
- return dataUrl;
888
-
889
- return Object.assign(media, {
890
- mimetype: options.mimetype,
891
- data: dataUrl.replace(`data:${options.mimetype};base64,`, '')
892
- });
893
- };
894
-
895
- window.WWebJS.setPicture = async (chatId, media) => {
896
- const thumbnail = await window.WWebJS.cropAndResizeImage(media, { asDataUrl: true, mimetype: 'image/jpeg', size: 96 });
897
- const profilePic = await window.WWebJS.cropAndResizeImage(media, { asDataUrl: true, mimetype: 'image/jpeg', size: 640 });
898
-
899
- const chatWid = window.Store.WidFactory.createWid(chatId);
900
- try {
901
- const collection = window.Store.ProfilePicThumb.get(chatId) || await window.Store.ProfilePicThumb.find(chatId);
902
- if (!collection?.canSet()) return false;
903
-
904
- const res = await window.Store.GroupUtils.sendSetPicture(chatWid, thumbnail, profilePic);
905
- return res ? res.status === 200 : false;
906
- } catch (err) {
907
- if (err.name === 'ServerStatusCodeError') return false;
908
- throw err;
909
- }
910
- };
911
-
912
- window.WWebJS.deletePicture = async (chatid) => {
913
- const chatWid = window.Store.WidFactory.createWid(chatid);
914
- try {
915
- const collection = window.Store.ProfilePicThumb.get(chatid);
916
- if (!collection.canDelete()) return;
917
-
918
- const res = await window.Store.GroupUtils.requestDeletePicture(chatWid);
919
- return res ? res.status === 200 : false;
920
- } catch (err) {
921
- if(err.name === 'ServerStatusCodeError') return false;
922
- throw err;
923
- }
924
- };
925
-
926
- window.WWebJS.getProfilePicThumbToBase64 = async (chatWid) => {
927
- const profilePicCollection = await window.Store.ProfilePicThumb.find(chatWid);
928
-
929
- const _readImageAsBase64 = (imageBlob) => {
930
- return new Promise((resolve) => {
931
- const reader = new FileReader();
932
- reader.onloadend = function () {
933
- const base64Image = reader.result;
934
- if (base64Image == null) {
935
- resolve(undefined);
936
- } else {
937
- const base64Data = base64Image.toString().split(',')[1];
938
- resolve(base64Data);
939
- }
940
- };
941
- reader.readAsDataURL(imageBlob);
942
- });
943
- };
944
-
945
- if (profilePicCollection?.img) {
946
- try {
947
- const response = await fetch(profilePicCollection.img);
948
- if (response.ok) {
949
- const imageBlob = await response.blob();
950
- if (imageBlob) {
951
- const base64Image = await _readImageAsBase64(imageBlob);
952
- return base64Image;
953
- }
954
- }
955
- } catch (error) { /* empty */ }
956
- }
957
- return undefined;
958
- };
959
-
960
- window.WWebJS.getAddParticipantsRpcResult = async (groupWid, participantWid) => {
961
- const iqTo = window.Store.WidToJid.widToGroupJid(groupWid);
962
-
963
- const participantArgs = [{
964
- participantJid: window.Store.WidToJid.widToUserJid(participantWid)
965
- }];
966
-
967
- let rpcResult, resultArgs;
968
- const data = {
969
- name: undefined,
970
- code: undefined,
971
- inviteV4Code: undefined,
972
- inviteV4CodeExp: undefined
973
- };
974
-
975
- try {
976
- rpcResult = await window.Store.GroupParticipants.sendAddParticipantsRPC({ participantArgs, iqTo });
977
- resultArgs = rpcResult.value.addParticipant[0]
978
- .addParticipantsParticipantAddedOrNonRegisteredWaUserParticipantErrorLidResponseMixinGroup
979
- .value
980
- .addParticipantsParticipantMixins;
981
- } catch (err) {
982
- data.code = 400;
983
- return data;
984
- }
985
-
986
- if (rpcResult.name === 'AddParticipantsResponseSuccess') {
987
- const code = resultArgs?.value.error || '200';
988
- data.name = resultArgs?.name;
989
- data.code = +code;
990
- data.inviteV4Code = resultArgs?.value.addRequestCode;
991
- data.inviteV4CodeExp = resultArgs?.value.addRequestExpiration?.toString();
992
- }
993
-
994
- else if (rpcResult.name === 'AddParticipantsResponseClientError') {
995
- const { code: code } = rpcResult.value.errorAddParticipantsClientErrors.value;
996
- data.code = +code;
997
- }
998
-
999
- else if (rpcResult.name === 'AddParticipantsResponseServerError') {
1000
- const { code: code } = rpcResult.value.errorServerErrors.value;
1001
- data.code = +code;
1002
- }
1003
-
1004
- return data;
1005
- };
1006
-
1007
- window.WWebJS.membershipRequestAction = async (groupId, action, requesterIds, sleep) => {
1008
- const groupWid = window.Store.WidFactory.createWid(groupId);
1009
- const group = await window.Store.Chat.find(groupWid);
1010
- const toApprove = action === 'Approve';
1011
- let membershipRequests;
1012
- let response;
1013
- let result = [];
1014
-
1015
- await window.Store.GroupQueryAndUpdate({ id: groupId });
1016
-
1017
- if (!requesterIds?.length) {
1018
- membershipRequests = group.groupMetadata.membershipApprovalRequests._models.map(({ id }) => id);
1019
- } else {
1020
- !Array.isArray(requesterIds) && (requesterIds = [requesterIds]);
1021
- membershipRequests = requesterIds.map(r => window.Store.WidFactory.createWid(r));
1022
- }
1023
-
1024
- if (!membershipRequests.length) return [];
1025
-
1026
- const participantArgs = membershipRequests.map(m => ({
1027
- participantArgs: [
1028
- {
1029
- participantJid: window.Store.WidToJid.widToUserJid(m)
1030
- }
1031
- ]
1032
- }));
1033
-
1034
- const groupJid = window.Store.WidToJid.widToGroupJid(groupWid);
1035
-
1036
- const _getSleepTime = (sleep) => {
1037
- if (!Array.isArray(sleep) || (sleep.length === 2 && sleep[0] === sleep[1])) {
1038
- return sleep;
1039
- }
1040
- if (sleep.length === 1) {
1041
- return sleep[0];
1042
- }
1043
- sleep[1] - sleep[0] < 100 && (sleep[0] = sleep[1]) && (sleep[1] += 100);
1044
- return Math.floor(Math.random() * (sleep[1] - sleep[0] + 1)) + sleep[0];
1045
- };
1046
-
1047
- const membReqResCodes = {
1048
- default: `An unknown error occupied while ${toApprove ? 'approving' : 'rejecting'} the participant membership request`,
1049
- 400: 'ParticipantNotFoundError',
1050
- 401: 'ParticipantNotAuthorizedError',
1051
- 403: 'ParticipantForbiddenError',
1052
- 404: 'ParticipantRequestNotFoundError',
1053
- 408: 'ParticipantTemporarilyBlockedError',
1054
- 409: 'ParticipantConflictError',
1055
- 412: 'ParticipantParentLinkedGroupsResourceConstraintError',
1056
- 500: 'ParticipantResourceConstraintError'
1057
- };
1058
-
1059
- try {
1060
- for (const participant of participantArgs) {
1061
- response = await window.Store.MembershipRequestUtils.sendMembershipRequestsActionRPC({
1062
- iqTo: groupJid,
1063
- [toApprove ? 'approveArgs' : 'rejectArgs']: participant
1064
- });
1065
-
1066
- if (response.name === 'MembershipRequestsActionResponseSuccess') {
1067
- const value = toApprove
1068
- ? response.value.membershipRequestsActionApprove
1069
- : response.value.membershipRequestsActionReject;
1070
- if (value?.participant) {
1071
- const [_] = value.participant.map(p => {
1072
- const error = toApprove
1073
- ? value.participant[0].membershipRequestsActionAcceptParticipantMixins?.value.error
1074
- : value.participant[0].membershipRequestsActionRejectParticipantMixins?.value.error;
1075
- return {
1076
- requesterId: window.Store.WidFactory.createWid(p.jid)._serialized,
1077
- ...(error
1078
- ? { error: +error, message: membReqResCodes[error] || membReqResCodes.default }
1079
- : { message: `${toApprove ? 'Approved' : 'Rejected'} successfully` })
1080
- };
1081
- });
1082
- _ && result.push(_);
1083
- }
1084
- } else {
1085
- result.push({
1086
- requesterId: window.Store.JidToWid.userJidToUserWid(participant.participantArgs[0].participantJid)._serialized,
1087
- message: 'ServerStatusCodeError'
1088
- });
1089
- }
1090
-
1091
- sleep &&
1092
- participantArgs.length > 1 &&
1093
- participantArgs.indexOf(participant) !== participantArgs.length - 1 &&
1094
- (await new Promise((resolve) => setTimeout(resolve, _getSleepTime(sleep))));
1095
- }
1096
- return result;
1097
- } catch (err) {
1098
- return [];
1099
- }
1100
- };
1101
-
1102
- window.WWebJS.subscribeToUnsubscribeFromChannel = async (channelId, action, options = {}) => {
1103
- const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
1104
-
1105
- if (!channel || channel.newsletterMetadata.membershipType === 'owner') return false;
1106
- options = { eventSurface: 3, deleteLocalModels: options.deleteLocalModels ?? true };
1107
-
1108
- try {
1109
- if (action === 'Subscribe') {
1110
- await window.Store.ChannelUtils.subscribeToNewsletterAction(channel, options);
1111
- } else if (action === 'Unsubscribe') {
1112
- await window.Store.ChannelUtils.unsubscribeFromNewsletterAction(channel, options);
1113
- } else return false;
1114
- return true;
1115
- } catch (err) {
1116
- if (err.name === 'ServerStatusCodeError') return false;
1117
- throw err;
1118
- }
1119
- };
1120
-
1121
- window.WWebJS.pinUnpinMsgAction = async (msgId, action, duration) => {
1122
- const message = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
1123
- if (!message) return false;
1124
-
1125
- if (typeof duration !== 'number') return false;
1126
-
1127
- const originalFunction = window.require('WAWebPinMsgConstants').getPinExpiryDuration;
1128
- window.require('WAWebPinMsgConstants').getPinExpiryDuration = () => duration;
1129
-
1130
- const response = await window.Store.PinnedMsgUtils.sendPinInChatMsg(message, action, duration);
1131
-
1132
- window.require('WAWebPinMsgConstants').getPinExpiryDuration = originalFunction;
1133
-
1134
- return response.messageSendResult === 'OK';
1135
- };
1136
-
1137
- window.WWebJS.getStatusModel = status => {
1138
- const res = status.serialize();
1139
- delete res._msgs;
1140
- return res;
1141
- };
1142
-
1143
- window.WWebJS.getAllStatuses = () => {
1144
- const statuses = window.Store.Status.getModelsArray();
1145
- return statuses.map(status => window.WWebJS.getStatusModel(status));
1146
- };
1147
-
1148
- window.WWebJS.enforceLidAndPnRetrieval = async (userId) => {
1149
- const wid = window.Store.WidFactory.createWid(userId);
1150
- const isLid = wid.server === 'lid';
1151
-
1152
- let lid = isLid ? wid : window.Store.LidUtils.getCurrentLid(wid);
1153
- let phone = isLid ? window.Store.LidUtils.getPhoneNumber(wid) : wid;
1154
-
1155
- if (!isLid && !lid) {
1156
- const queryResult = await window.Store.QueryExist(wid);
1157
- if (!queryResult?.wid) return {};
1158
- lid = window.Store.LidUtils.getCurrentLid(wid);
1159
- }
1160
-
1161
- if (isLid && !phone) {
1162
- const queryResult = await window.Store.QueryExist(wid);
1163
- if (!queryResult?.wid) return {};
1164
- phone = window.Store.LidUtils.getPhoneNumber(wid);
1165
- }
1166
-
1167
- return { lid, phone };
1168
- };
1169
- };
1
+ 'use strict';
2
+
3
+ exports.LoadUtils = () => {
4
+ window.WWebJS = {};
5
+
6
+ window.WWebJS.forwardMessage = async (chatId, msgId) => {
7
+ const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
8
+ const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
9
+ return window.Store.ForwardUtils.forwardMessages(chat, [msg], true, true);
10
+ };
11
+
12
+ window.WWebJS.sendSeen = async (chatId) => {
13
+ const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
14
+ if (chat) {
15
+ window.Store.WAWebStreamModel.Stream.markAvailable();
16
+ await window.Store.SendSeen.sendSeen(chat);
17
+ window.Store.WAWebStreamModel.Stream.markUnavailable();
18
+ return true;
19
+ }
20
+ return false;
21
+ };
22
+
23
+ window.WWebJS.sendMessage = async (chat, content, options = {}) => {
24
+ const isChannel = window.Store.ChatGetters.getIsNewsletter(chat);
25
+
26
+ let mediaOptions = {};
27
+ if (options.media) {
28
+ mediaOptions = options.sendMediaAsSticker && !isChannel
29
+ ? await window.WWebJS.processStickerData(options.media)
30
+ : await window.WWebJS.processMediaData(options.media, {
31
+ forceSticker: options.sendMediaAsSticker,
32
+ forceGif: options.sendVideoAsGif,
33
+ forceVoice: options.sendAudioAsVoice,
34
+ forceDocument: options.sendMediaAsDocument,
35
+ forceMediaHd: options.sendMediaAsHd,
36
+ sendToChannel: isChannel
37
+ });
38
+ mediaOptions.caption = options.caption;
39
+ content = options.sendMediaAsSticker ? undefined : mediaOptions.preview;
40
+ mediaOptions.isViewOnce = options.isViewOnce;
41
+ delete options.media;
42
+ delete options.sendMediaAsSticker;
43
+ }
44
+
45
+ let quotedMsgOptions = {};
46
+ if (options.quotedMessageId) {
47
+ let quotedMessage = window.Store.Msg.get(options.quotedMessageId);
48
+ !quotedMessage && (quotedMessage = (await window.Store.Msg.getMessagesById([options.quotedMessageId]))?.messages?.[0]);
49
+ if (quotedMessage) {
50
+
51
+ const canReply = window.Store.ReplyUtils
52
+ ? window.Store.ReplyUtils.canReplyMsg(quotedMessage.unsafe())
53
+ : quotedMessage.canReply();
54
+
55
+ if (canReply) {
56
+ quotedMsgOptions = quotedMessage.msgContextInfo(chat);
57
+ }
58
+ } else {
59
+ if (!options.ignoreQuoteErrors) {
60
+ throw new Error('Could not get the quoted message.');
61
+ }
62
+ }
63
+
64
+ delete options.ignoreQuoteErrors;
65
+ delete options.quotedMessageId;
66
+ }
67
+
68
+ if (options.mentionedJidList) {
69
+ options.mentionedJidList = options.mentionedJidList.map((id) => window.Store.WidFactory.createWid(id));
70
+ options.mentionedJidList = options.mentionedJidList.filter(Boolean);
71
+ }
72
+
73
+ if (options.groupMentions) {
74
+ options.groupMentions = options.groupMentions.map((e) => ({
75
+ groupSubject: e.subject,
76
+ groupJid: window.Store.WidFactory.createWid(e.id)
77
+ }));
78
+ }
79
+
80
+ let locationOptions = {};
81
+ if (options.location) {
82
+ let { latitude, longitude, description, url } = options.location;
83
+ url = window.Store.Validators.findLink(url)?.href;
84
+ url && !description && (description = url);
85
+ locationOptions = {
86
+ type: 'location',
87
+ loc: description,
88
+ lat: latitude,
89
+ lng: longitude,
90
+ clientUrl: url
91
+ };
92
+ delete options.location;
93
+ }
94
+
95
+ let _pollOptions = {};
96
+ if (options.poll) {
97
+ const { pollName, pollOptions } = options.poll;
98
+ const { allowMultipleAnswers, messageSecret } = options.poll.options;
99
+ _pollOptions = {
100
+ kind: 'pollCreation',
101
+ type: 'poll_creation',
102
+ pollName: pollName,
103
+ pollOptions: pollOptions,
104
+ pollSelectableOptionsCount: allowMultipleAnswers ? 0 : 1,
105
+ messageSecret:
106
+ Array.isArray(messageSecret) && messageSecret.length === 32
107
+ ? new Uint8Array(messageSecret)
108
+ : window.crypto.getRandomValues(new Uint8Array(32))
109
+ };
110
+ delete options.poll;
111
+ }
112
+
113
+ let eventOptions = {};
114
+ if (options.event) {
115
+ const { name, startTimeTs, eventSendOptions } = options.event;
116
+ const { messageSecret } = eventSendOptions;
117
+ eventOptions = {
118
+ type: 'event_creation',
119
+ eventName: name,
120
+ eventDescription: eventSendOptions.description,
121
+ eventStartTime: startTimeTs,
122
+ eventEndTime: eventSendOptions.endTimeTs,
123
+ eventLocation: eventSendOptions.location && {
124
+ degreesLatitude: 0,
125
+ degreesLongitude: 0,
126
+ name: eventSendOptions.location
127
+ },
128
+ eventJoinLink: await window.Store.ScheduledEventMsgUtils.createEventCallLink(
129
+ startTimeTs,
130
+ eventSendOptions.callType
131
+ ),
132
+ isEventCanceled: eventSendOptions.isEventCanceled,
133
+ messageSecret:
134
+ Array.isArray(messageSecret) && messageSecret.length === 32
135
+ ? new Uint8Array(messageSecret)
136
+ : window.crypto.getRandomValues(new Uint8Array(32)),
137
+ };
138
+ delete options.event;
139
+ }
140
+
141
+ let vcardOptions = {};
142
+ if (options.contactCard) {
143
+ let contact = window.Store.Contact.get(options.contactCard);
144
+ vcardOptions = {
145
+ body: window.Store.VCard.vcardFromContactModel(contact).vcard,
146
+ type: 'vcard',
147
+ vcardFormattedName: contact.formattedName
148
+ };
149
+ delete options.contactCard;
150
+ } else if (options.contactCardList) {
151
+ let contacts = options.contactCardList.map(c => window.Store.Contact.get(c));
152
+ let vcards = contacts.map(c => window.Store.VCard.vcardFromContactModel(c));
153
+ vcardOptions = {
154
+ type: 'multi_vcard',
155
+ vcardList: vcards,
156
+ body: null
157
+ };
158
+ delete options.contactCardList;
159
+ } else if (options.parseVCards && typeof (content) === 'string' && content.startsWith('BEGIN:VCARD')) {
160
+ delete options.parseVCards;
161
+ delete options.linkPreview;
162
+ try {
163
+ const parsed = window.Store.VCard.parseVcard(content);
164
+ if (parsed) {
165
+ vcardOptions = {
166
+ type: 'vcard',
167
+ vcardFormattedName: window.Store.VCard.vcardGetNameFromParsed(parsed)
168
+ };
169
+ }
170
+ } catch (_) {
171
+ // not a vcard
172
+ }
173
+ }
174
+
175
+ if (options.linkPreview) {
176
+ delete options.linkPreview;
177
+ const link = window.Store.Validators.findLink(content);
178
+ if (link) {
179
+ let preview = await window.Store.LinkPreview.getLinkPreview(link);
180
+ if (preview && preview.data) {
181
+ preview = preview.data;
182
+ preview.preview = true;
183
+ preview.subtype = 'url';
184
+ options = {...options, ...preview};
185
+ }
186
+ }
187
+ }
188
+
189
+ let buttonOptions = {};
190
+ if (options.buttons) {
191
+ let caption;
192
+ if (options.buttons.type === 'chat') {
193
+ content = options.buttons.body;
194
+ caption = content;
195
+ } else {
196
+ caption = options.caption ? options.caption : ' '; //Caption can't be empty
197
+ }
198
+ buttonOptions = {
199
+ productHeaderImageRejected: false,
200
+ isFromTemplate: false,
201
+ isDynamicReplyButtonsMsg: true,
202
+ title: options.buttons.title ? options.buttons.title : undefined,
203
+ footer: options.buttons.footer ? options.buttons.footer : undefined,
204
+ dynamicReplyButtons: options.buttons.buttons,
205
+ replyButtons: options.buttons.buttons,
206
+ caption: caption
207
+ };
208
+ delete options.buttons;
209
+ }
210
+
211
+ let listOptions = {};
212
+ if (options.list) {
213
+ if (window.Store.Conn.platform === 'smba' || window.Store.Conn.platform === 'smbi') {
214
+ throw '[LT01] Whatsapp business can\'t send this yet';
215
+ }
216
+ listOptions = {
217
+ type: 'list',
218
+ footer: options.list.footer,
219
+ list: {
220
+ ...options.list,
221
+ listType: 1
222
+ },
223
+ body: options.list.description
224
+ };
225
+ delete options.list;
226
+ delete listOptions.list.footer;
227
+ }
228
+
229
+ const botOptions = {};
230
+ if (options.invokedBotWid) {
231
+ botOptions.messageSecret = window.crypto.getRandomValues(new Uint8Array(32));
232
+ botOptions.botMessageSecret = await window.Store.BotSecret.genBotMsgSecretFromMsgSecret(botOptions.messageSecret);
233
+ botOptions.invokedBotWid = window.Store.WidFactory.createWid(options.invokedBotWid);
234
+ botOptions.botPersonaId = window.Store.BotProfiles.BotProfileCollection.get(options.invokedBotWid).personaId;
235
+ delete options.invokedBotWid;
236
+ }
237
+
238
+ const lidUser = window.Store.User.getMaybeMeLidUser();
239
+ const meUser = window.Store.User.getMaybeMePnUser();
240
+ const newId = await window.Store.MsgKey.newId();
241
+ let from = chat.id.isLid() ? lidUser : meUser;
242
+ let participant;
243
+
244
+ if (typeof chat.id?.isGroup === 'function' && chat.id.isGroup()) {
245
+ from = chat.groupMetadata && chat.groupMetadata.isLidAddressingMode ? lidUser : meUser;
246
+ participant = window.Store.WidFactory.asUserWidOrThrow(from);
247
+ }
248
+
249
+ const newMsgKey = new window.Store.MsgKey({
250
+ from: from,
251
+ to: chat.id,
252
+ id: newId,
253
+ participant: participant,
254
+ selfDir: 'out',
255
+ });
256
+
257
+ const extraOptions = options.extraOptions || {};
258
+ delete options.extraOptions;
259
+
260
+ const ephemeralFields = window.Store.EphemeralFields.getEphemeralFields(chat);
261
+
262
+ const message = {
263
+ ...options,
264
+ id: newMsgKey,
265
+ ack: 0,
266
+ body: content,
267
+ from: meUser,
268
+ to: chat.id,
269
+ local: true,
270
+ self: 'out',
271
+ t: parseInt(new Date().getTime() / 1000),
272
+ isNewMsg: true,
273
+ type: 'chat',
274
+ ...ephemeralFields,
275
+ ...mediaOptions,
276
+ ...(mediaOptions.toJSON ? mediaOptions.toJSON() : {}),
277
+ ...quotedMsgOptions,
278
+ ...locationOptions,
279
+ ..._pollOptions,
280
+ ...eventOptions,
281
+ ...vcardOptions,
282
+ ...buttonOptions,
283
+ ...listOptions,
284
+ ...botOptions,
285
+ ...extraOptions
286
+ };
287
+
288
+ // Bot's won't reply if canonicalUrl is set (linking)
289
+ if (botOptions) {
290
+ delete message.canonicalUrl;
291
+ }
292
+
293
+ if (isChannel) {
294
+ const msg = new window.Store.Msg.modelClass(message);
295
+ const msgDataFromMsgModel = window.Store.SendChannelMessage.msgDataFromMsgModel(msg);
296
+ const isMedia = Object.keys(mediaOptions).length > 0;
297
+ await window.Store.SendChannelMessage.addNewsletterMsgsRecords([msgDataFromMsgModel]);
298
+ chat.msgs.add(msg);
299
+ chat.t = msg.t;
300
+
301
+ const sendChannelMsgResponse = await window.Store.SendChannelMessage.sendNewsletterMessageJob({
302
+ msg: msg,
303
+ type: message.type === 'chat' ? 'text' : isMedia ? 'media' : 'pollCreation',
304
+ newsletterJid: chat.id.toJid(),
305
+ ...(isMedia
306
+ ? {
307
+ mediaMetadata: msg.avParams(),
308
+ mediaHandle: isMedia ? mediaOptions.mediaHandle : null,
309
+ }
310
+ : {}
311
+ )
312
+ });
313
+
314
+ if (sendChannelMsgResponse.success) {
315
+ msg.t = sendChannelMsgResponse.ack.t;
316
+ msg.serverId = sendChannelMsgResponse.serverId;
317
+ }
318
+ msg.updateAck(1, true);
319
+ await window.Store.SendChannelMessage.updateNewsletterMsgRecord(msg);
320
+ return msg;
321
+ }
322
+
323
+ const [msgPromise, sendMsgResultPromise] = window.Store.SendMessage.addAndSendMsgToChat(chat, message);
324
+ await msgPromise;
325
+
326
+ if (options.waitUntilMsgSent) await sendMsgResultPromise;
327
+
328
+ return window.Store.Msg.get(newMsgKey._serialized);
329
+ };
330
+
331
+ window.WWebJS.editMessage = async (msg, content, options = {}) => {
332
+ const extraOptions = options.extraOptions || {};
333
+ delete options.extraOptions;
334
+
335
+ if (options.mentionedJidList) {
336
+ options.mentionedJidList = options.mentionedJidList.map((id) => window.Store.WidFactory.createWid(id));
337
+ options.mentionedJidList = options.mentionedJidList.filter(Boolean);
338
+ }
339
+
340
+ if (options.groupMentions) {
341
+ options.groupMentions = options.groupMentions.map((e) => ({
342
+ groupSubject: e.subject,
343
+ groupJid: window.Store.WidFactory.createWid(e.id)
344
+ }));
345
+ }
346
+
347
+ if (options.linkPreview) {
348
+ delete options.linkPreview;
349
+ const link = window.Store.Validators.findLink(content);
350
+ if (link) {
351
+ const preview = await window.Store.LinkPreview.getLinkPreview(link);
352
+ preview.preview = true;
353
+ preview.subtype = 'url';
354
+ options = { ...options, ...preview };
355
+ }
356
+ }
357
+
358
+
359
+ const internalOptions = {
360
+ ...options,
361
+ ...extraOptions
362
+ };
363
+
364
+ await window.Store.EditMessage.sendMessageEdit(msg, content, internalOptions);
365
+ return window.Store.Msg.get(msg.id._serialized);
366
+ };
367
+
368
+ window.WWebJS.toStickerData = async (mediaInfo) => {
369
+ if (mediaInfo.mimetype == 'image/webp') return mediaInfo;
370
+
371
+ const file = window.WWebJS.mediaInfoToFile(mediaInfo);
372
+ const webpSticker = await window.Store.StickerTools.toWebpSticker(file);
373
+ const webpBuffer = await webpSticker.arrayBuffer();
374
+ const data = window.WWebJS.arrayBufferToBase64(webpBuffer);
375
+
376
+ return {
377
+ mimetype: 'image/webp',
378
+ data
379
+ };
380
+ };
381
+
382
+ window.WWebJS.processStickerData = async (mediaInfo) => {
383
+ if (mediaInfo.mimetype !== 'image/webp') throw new Error('Invalid media type');
384
+
385
+ const file = window.WWebJS.mediaInfoToFile(mediaInfo);
386
+ let filehash = await window.WWebJS.getFileHash(file);
387
+ let mediaKey = await window.WWebJS.generateHash(32);
388
+
389
+ const controller = new AbortController();
390
+ const uploadedInfo = await window.Store.UploadUtils.encryptAndUpload({
391
+ blob: file,
392
+ type: 'sticker',
393
+ signal: controller.signal,
394
+ mediaKey
395
+ });
396
+
397
+ const stickerInfo = {
398
+ ...uploadedInfo,
399
+ clientUrl: uploadedInfo.url,
400
+ deprecatedMms3Url: uploadedInfo.url,
401
+ uploadhash: uploadedInfo.encFilehash,
402
+ size: file.size,
403
+ type: 'sticker',
404
+ filehash
405
+ };
406
+
407
+ return stickerInfo;
408
+ };
409
+
410
+ window.WWebJS.processMediaData = async (mediaInfo, { forceSticker, forceGif, forceVoice, forceDocument, forceMediaHd, sendToChannel }) => {
411
+ const file = window.WWebJS.mediaInfoToFile(mediaInfo);
412
+ const opaqueData = await window.Store.OpaqueData.createFromData(file, file.type);
413
+ const mediaParams = {
414
+ asSticker: forceSticker,
415
+ asGif: forceGif,
416
+ isPtt: forceVoice,
417
+ asDocument: forceDocument
418
+ };
419
+
420
+ if (forceMediaHd && file.type.indexOf('image/') === 0) {
421
+ mediaParams.maxDimension = 2560;
422
+ }
423
+
424
+ const mediaPrep = window.Store.MediaPrep.prepRawMedia(opaqueData, mediaParams);
425
+ const mediaData = await mediaPrep.waitForPrep();
426
+ const mediaObject = window.Store.MediaObject.getOrCreateMediaObject(mediaData.filehash);
427
+ const mediaType = window.Store.MediaTypes.msgToMediaType({
428
+ type: mediaData.type,
429
+ isGif: mediaData.isGif,
430
+ isNewsletter: sendToChannel,
431
+ });
432
+
433
+ if (forceVoice && mediaData.type === 'ptt') {
434
+ const waveform = mediaObject.contentInfo.waveform;
435
+ mediaData.waveform =
436
+ waveform || await window.WWebJS.generateWaveform(file);
437
+ }
438
+
439
+ if (!(mediaData.mediaBlob instanceof window.Store.OpaqueData)) {
440
+ mediaData.mediaBlob = await window.Store.OpaqueData.createFromData(
441
+ mediaData.mediaBlob,
442
+ mediaData.mediaBlob.type
443
+ );
444
+ }
445
+
446
+ mediaData.renderableUrl = mediaData.mediaBlob.url();
447
+ mediaObject.consolidate(mediaData.toJSON());
448
+ mediaData.mediaBlob.autorelease();
449
+
450
+ const dataToUpload = {
451
+ mimetype: mediaData.mimetype,
452
+ mediaObject,
453
+ mediaType,
454
+ ...(sendToChannel ? { calculateToken: window.Store.SendChannelMessage.getRandomFilehash } : {})
455
+ };
456
+
457
+ const uploadedMedia = !sendToChannel
458
+ ? await window.Store.MediaUpload.uploadMedia(dataToUpload)
459
+ : await window.Store.MediaUpload.uploadUnencryptedMedia(dataToUpload);
460
+
461
+ const mediaEntry = uploadedMedia.mediaEntry;
462
+ if (!mediaEntry) {
463
+ throw new Error('upload failed: media entry was not created');
464
+ }
465
+
466
+ mediaData.set({
467
+ clientUrl: mediaEntry.mmsUrl,
468
+ deprecatedMms3Url: mediaEntry.deprecatedMms3Url,
469
+ directPath: mediaEntry.directPath,
470
+ mediaKey: mediaEntry.mediaKey,
471
+ mediaKeyTimestamp: mediaEntry.mediaKeyTimestamp,
472
+ filehash: mediaObject.filehash,
473
+ encFilehash: mediaEntry.encFilehash,
474
+ uploadhash: mediaEntry.uploadHash,
475
+ size: mediaObject.size,
476
+ streamingSidecar: mediaEntry.sidecar,
477
+ firstFrameSidecar: mediaEntry.firstFrameSidecar,
478
+ mediaHandle: sendToChannel ? mediaEntry.handle : null,
479
+ });
480
+
481
+ return mediaData;
482
+ };
483
+
484
+ window.WWebJS.getMessageModel = (message) => {
485
+ const msg = message.serialize();
486
+
487
+ msg.isEphemeral = message.isEphemeral;
488
+ msg.isStatusV3 = message.isStatusV3;
489
+ msg.links = (window.Store.Validators.findLinks(message.mediaObject ? message.caption : message.body)).map((link) => ({
490
+ link: link.href,
491
+ isSuspicious: Boolean(link.suspiciousCharacters && link.suspiciousCharacters.size)
492
+ }));
493
+
494
+ if (msg.buttons) {
495
+ msg.buttons = msg.buttons.serialize();
496
+ }
497
+ if (msg.dynamicReplyButtons) {
498
+ msg.dynamicReplyButtons = JSON.parse(JSON.stringify(msg.dynamicReplyButtons));
499
+ }
500
+ if (msg.replyButtons) {
501
+ msg.replyButtons = JSON.parse(JSON.stringify(msg.replyButtons));
502
+ }
503
+
504
+ if (typeof msg.id.remote === 'object') {
505
+ msg.id = Object.assign({}, msg.id, { remote: msg.id.remote._serialized });
506
+ }
507
+
508
+ delete msg.pendingAckUpdate;
509
+
510
+ return msg;
511
+ };
512
+
513
+ window.WWebJS.getChat = async (chatId, { getAsModel = true } = {}) => {
514
+ const isChannel = /@\w*newsletter\b/.test(chatId);
515
+ const chatWid = window.Store.WidFactory.createWid(chatId);
516
+ let chat;
517
+
518
+ if (isChannel) {
519
+ try {
520
+ chat = window.Store.NewsletterCollection.get(chatId);
521
+ if (!chat) {
522
+ await window.Store.ChannelUtils.loadNewsletterPreviewChat(chatId);
523
+ chat = await window.Store.NewsletterCollection.find(chatWid);
524
+ }
525
+ } catch (err) {
526
+ chat = null;
527
+ }
528
+ } else {
529
+ chat = window.Store.Chat.get(chatWid) || (await window.Store.FindOrCreateChat.findOrCreateLatestChat(chatWid))?.chat;
530
+ }
531
+
532
+ return getAsModel && chat
533
+ ? await window.WWebJS.getChatModel(chat, { isChannel: isChannel })
534
+ : chat;
535
+ };
536
+
537
+ window.WWebJS.getChannelMetadata = async (inviteCode) => {
538
+ const response =
539
+ await window.Store.ChannelUtils.queryNewsletterMetadataByInviteCode(
540
+ inviteCode,
541
+ window.Store.ChannelUtils.getRoleByIdentifier(inviteCode)
542
+ );
543
+
544
+ const picUrl = response.newsletterPictureMetadataMixin?.picture[0]?.queryPictureDirectPathOrEmptyResponseMixinGroup.value.directPath;
545
+
546
+ return {
547
+ id: response.idJid,
548
+ createdAtTs: response.newsletterCreationTimeMetadataMixin.creationTimeValue,
549
+ titleMetadata: {
550
+ title: response.newsletterNameMetadataMixin.nameElementValue,
551
+ updatedAtTs: response.newsletterNameMetadataMixin.nameUpdateTime
552
+ },
553
+ descriptionMetadata: {
554
+ description: response.newsletterDescriptionMetadataMixin.descriptionQueryDescriptionResponseMixin.elementValue,
555
+ updatedAtTs: response.newsletterDescriptionMetadataMixin.descriptionQueryDescriptionResponseMixin.updateTime
556
+ },
557
+ inviteLink: `https://whatsapp.com/channel/${response.newsletterInviteLinkMetadataMixin.inviteCode}`,
558
+ membershipType: window.Store.ChannelUtils.getRoleByIdentifier(inviteCode),
559
+ stateType: response.newsletterStateMetadataMixin.stateType,
560
+ pictureUrl: picUrl ? `https://pps.whatsapp.net${picUrl}` : null,
561
+ subscribersCount: response.newsletterSubscribersMetadataMixin.subscribersCount,
562
+ isVerified: response.newsletterVerificationMetadataMixin.verificationState === 'verified'
563
+ };
564
+ };
565
+
566
+ window.WWebJS.getChats = async () => {
567
+ const chats = window.Store.Chat.getModelsArray();
568
+ const chatPromises = chats.map(chat => window.WWebJS.getChatModel(chat));
569
+ return await Promise.all(chatPromises);
570
+ };
571
+
572
+ window.WWebJS.getChannels = async () => {
573
+ const channels = window.Store.NewsletterCollection.getModelsArray();
574
+ const channelPromises = channels?.map((channel) => window.WWebJS.getChatModel(channel, { isChannel: true }));
575
+ return await Promise.all(channelPromises);
576
+ };
577
+
578
+ window.WWebJS.getChatModel = async (chat, { isChannel = false } = {}) => {
579
+ if (!chat) return null;
580
+
581
+ const model = chat.serialize();
582
+ model.isGroup = false;
583
+ model.isMuted = chat.mute?.expiration !== 0;
584
+ if (isChannel) {
585
+ model.isChannel = window.Store.ChatGetters.getIsNewsletter(chat);
586
+ } else {
587
+ model.formattedTitle = chat.formattedTitle;
588
+ }
589
+
590
+ if (chat.groupMetadata) {
591
+ model.isGroup = true;
592
+ const chatWid = window.Store.WidFactory.createWid(chat.id._serialized);
593
+ await window.Store.GroupMetadata.update(chatWid);
594
+ chat.groupMetadata.participants._models
595
+ .filter(x => x.id?._serialized?.endsWith('@lid'))
596
+ .forEach(x => x.contact?.phoneNumber && (x.id = x.contact.phoneNumber));
597
+ model.groupMetadata = chat.groupMetadata.serialize();
598
+ model.isReadOnly = chat.groupMetadata.announce;
599
+ }
600
+
601
+ if (chat.newsletterMetadata) {
602
+ await window.Store.NewsletterMetadataCollection.update(chat.id);
603
+ model.channelMetadata = chat.newsletterMetadata.serialize();
604
+ model.channelMetadata.createdAtTs = chat.newsletterMetadata.creationTime;
605
+ }
606
+
607
+ model.lastMessage = null;
608
+ if (model.msgs && model.msgs.length) {
609
+ const lastMessage = chat.lastReceivedKey
610
+ ? window.Store.Msg.get(chat.lastReceivedKey._serialized) || (await window.Store.Msg.getMessagesById([chat.lastReceivedKey._serialized]))?.messages?.[0]
611
+ : null;
612
+ lastMessage && (model.lastMessage = window.WWebJS.getMessageModel(lastMessage));
613
+ }
614
+
615
+ delete model.msgs;
616
+ delete model.msgUnsyncedButtonReplyMsgs;
617
+ delete model.unsyncedButtonReplies;
618
+
619
+ return model;
620
+ };
621
+
622
+ window.WWebJS.getContactModel = contact => {
623
+ let res = contact.serialize();
624
+ res.isBusiness = contact.isBusiness === undefined ? false : contact.isBusiness;
625
+
626
+ if (contact.businessProfile) {
627
+ res.businessProfile = contact.businessProfile.serialize();
628
+ }
629
+
630
+ res.isMe = window.Store.ContactMethods.getIsMe(contact);
631
+ res.isUser = window.Store.ContactMethods.getIsUser(contact);
632
+ res.isGroup = window.Store.ContactMethods.getIsGroup(contact);
633
+ res.isWAContact = window.Store.ContactMethods.getIsWAContact(contact);
634
+ res.isMyContact = window.Store.ContactMethods.getIsMyContact(contact);
635
+ res.isBlocked = contact.isContactBlocked;
636
+ res.userid = window.Store.ContactMethods.getUserid(contact);
637
+ res.isEnterprise = window.Store.ContactMethods.getIsEnterprise(contact);
638
+ res.verifiedName = window.Store.ContactMethods.getVerifiedName(contact);
639
+ res.verifiedLevel = window.Store.ContactMethods.getVerifiedLevel(contact);
640
+ res.statusMute = window.Store.ContactMethods.getStatusMute(contact);
641
+ res.name = window.Store.ContactMethods.getName(contact);
642
+ res.shortName = window.Store.ContactMethods.getShortName(contact);
643
+ res.pushname = window.Store.ContactMethods.getPushname(contact);
644
+
645
+ return res;
646
+ };
647
+
648
+ window.WWebJS.getContact = async contactId => {
649
+ const wid = window.Store.WidFactory.createWid(contactId);
650
+ let contact = await window.Store.Contact.find(wid);
651
+ if (contact.id._serialized.endsWith('@lid')) {
652
+ contact.id = contact.phoneNumber;
653
+ }
654
+ const bizProfile = await window.Store.BusinessProfile.fetchBizProfile(wid);
655
+ bizProfile.profileOptions && (contact.businessProfile = bizProfile);
656
+ return window.WWebJS.getContactModel(contact);
657
+ };
658
+
659
+ window.WWebJS.getContacts = () => {
660
+ const contacts = window.Store.Contact.getModelsArray();
661
+ return contacts.map(contact => window.WWebJS.getContactModel(contact));
662
+ };
663
+
664
+ window.WWebJS.mediaInfoToFile = ({ data, mimetype, filename }) => {
665
+ const binaryData = window.atob(data);
666
+
667
+ const buffer = new ArrayBuffer(binaryData.length);
668
+ const view = new Uint8Array(buffer);
669
+ for (let i = 0; i < binaryData.length; i++) {
670
+ view[i] = binaryData.charCodeAt(i);
671
+ }
672
+
673
+ const blob = new Blob([buffer], { type: mimetype });
674
+ return new File([blob], filename, {
675
+ type: mimetype,
676
+ lastModified: Date.now()
677
+ });
678
+ };
679
+
680
+ window.WWebJS.arrayBufferToBase64 = (arrayBuffer) => {
681
+ let binary = '';
682
+ const bytes = new Uint8Array(arrayBuffer);
683
+ const len = bytes.byteLength;
684
+ for (let i = 0; i < len; i++) {
685
+ binary += String.fromCharCode(bytes[i]);
686
+ }
687
+ return window.btoa(binary);
688
+ };
689
+
690
+ window.WWebJS.arrayBufferToBase64Async = (arrayBuffer) =>
691
+ new Promise((resolve, reject) => {
692
+ const blob = new Blob([arrayBuffer], {
693
+ type: 'application/octet-stream',
694
+ });
695
+ const fileReader = new FileReader();
696
+ fileReader.onload = () => {
697
+ const [, data] = fileReader.result.split(',');
698
+ resolve(data);
699
+ };
700
+ fileReader.onerror = (e) => reject(e);
701
+ fileReader.readAsDataURL(blob);
702
+ });
703
+
704
+ window.WWebJS.getFileHash = async (data) => {
705
+ let buffer = await data.arrayBuffer();
706
+ const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
707
+ return btoa(String.fromCharCode(...new Uint8Array(hashBuffer)));
708
+ };
709
+
710
+ window.WWebJS.generateHash = async (length) => {
711
+ var result = '';
712
+ var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
713
+ var charactersLength = characters.length;
714
+ for (var i = 0; i < length; i++) {
715
+ result += characters.charAt(Math.floor(Math.random() * charactersLength));
716
+ }
717
+ return result;
718
+ };
719
+
720
+ window.WWebJS.generateWaveform = async (audioFile) => {
721
+ try {
722
+ const audioData = await audioFile.arrayBuffer();
723
+ const audioContext = new AudioContext();
724
+ const audioBuffer = await audioContext.decodeAudioData(audioData);
725
+
726
+ const rawData = audioBuffer.getChannelData(0);
727
+ const samples = 64;
728
+ const blockSize = Math.floor(rawData.length / samples);
729
+ const filteredData = [];
730
+ for (let i = 0; i < samples; i++) {
731
+ const blockStart = blockSize * i;
732
+ let sum = 0;
733
+ for (let j = 0; j < blockSize; j++) {
734
+ sum = sum + Math.abs(rawData[blockStart + j]);
735
+ }
736
+ filteredData.push(sum / blockSize);
737
+ }
738
+
739
+ const multiplier = Math.pow(Math.max(...filteredData), -1);
740
+ const normalizedData = filteredData.map((n) => n * multiplier);
741
+
742
+ const waveform = new Uint8Array(
743
+ normalizedData.map((n) => Math.floor(100 * n))
744
+ );
745
+
746
+ return waveform;
747
+ } catch (e) {
748
+ return undefined;
749
+ }
750
+ };
751
+
752
+ window.WWebJS.sendClearChat = async (chatId) => {
753
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
754
+ if (chat !== undefined) {
755
+ await window.Store.SendClear.sendClear(chat, false);
756
+ return true;
757
+ }
758
+ return false;
759
+ };
760
+
761
+ window.WWebJS.sendDeleteChat = async (chatId) => {
762
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
763
+ if (chat !== undefined) {
764
+ await window.Store.SendDelete.sendDelete(chat);
765
+ return true;
766
+ }
767
+ return false;
768
+ };
769
+
770
+ window.WWebJS.sendChatstate = async (state, chatId) => {
771
+ chatId = window.Store.WidFactory.createWid(chatId);
772
+
773
+ switch (state) {
774
+ case 'typing':
775
+ await window.Store.ChatState.sendChatStateComposing(chatId);
776
+ break;
777
+ case 'recording':
778
+ await window.Store.ChatState.sendChatStateRecording(chatId);
779
+ break;
780
+ case 'stop':
781
+ await window.Store.ChatState.sendChatStatePaused(chatId);
782
+ break;
783
+ default:
784
+ throw 'Invalid chatstate';
785
+ }
786
+
787
+ return true;
788
+ };
789
+
790
+ window.WWebJS.getLabelModel = label => {
791
+ let res = label.serialize();
792
+ res.hexColor = label.hexColor;
793
+
794
+ return res;
795
+ };
796
+
797
+ window.WWebJS.getLabels = () => {
798
+ const labels = window.Store.Label.getModelsArray();
799
+ return labels.map(label => window.WWebJS.getLabelModel(label));
800
+ };
801
+
802
+ window.WWebJS.getLabel = (labelId) => {
803
+ const label = window.Store.Label.get(labelId);
804
+ return window.WWebJS.getLabelModel(label);
805
+ };
806
+
807
+ window.WWebJS.getChatLabels = async (chatId) => {
808
+ const chat = await window.WWebJS.getChat(chatId);
809
+ return (chat.labels || []).map(id => window.WWebJS.getLabel(id));
810
+ };
811
+
812
+ window.WWebJS.getOrderDetail = async (orderId, token, chatId) => {
813
+ const chatWid = window.Store.WidFactory.createWid(chatId);
814
+ return window.Store.QueryOrder.queryOrder(chatWid, orderId, 80, 80, token);
815
+ };
816
+
817
+ window.WWebJS.getProductMetadata = async (productId) => {
818
+ let sellerId = window.Store.Conn.wid;
819
+ let product = await window.Store.QueryProduct.queryProduct(sellerId, productId);
820
+ if (product && product.data) {
821
+ return product.data;
822
+ }
823
+
824
+ return undefined;
825
+ };
826
+
827
+ window.WWebJS.rejectCall = async (peerJid, id) => {
828
+ peerJid = peerJid.split('@')[0] + '@s.whatsapp.net';
829
+ let userId = window.Store.User.getMaybeMePnUser().user + '@s.whatsapp.net';
830
+ const stanza = window.Store.SocketWap.wap('call', {
831
+ id: window.Store.SocketWap.generateId(),
832
+ from: window.Store.SocketWap.USER_JID(userId),
833
+ to: window.Store.SocketWap.USER_JID(peerJid),
834
+ }, [
835
+ window.Store.SocketWap.wap('reject', {
836
+ 'call-id': id,
837
+ 'call-creator': window.Store.SocketWap.USER_JID(peerJid),
838
+ count: '0',
839
+ })
840
+ ]);
841
+ await window.Store.Socket.deprecatedCastStanza(stanza);
842
+ };
843
+
844
+ window.WWebJS.cropAndResizeImage = async (media, options = {}) => {
845
+ if (!media.mimetype.includes('image'))
846
+ throw new Error('Media is not an image');
847
+
848
+ if (options.mimetype && !options.mimetype.includes('image'))
849
+ delete options.mimetype;
850
+
851
+ options = Object.assign({ size: 640, mimetype: media.mimetype, quality: .75, asDataUrl: false }, options);
852
+
853
+ const img = await new Promise ((resolve, reject) => {
854
+ const img = new Image();
855
+ img.onload = () => resolve(img);
856
+ img.onerror = reject;
857
+ img.src = `data:${media.mimetype};base64,${media.data}`;
858
+ });
859
+
860
+ const sl = Math.min(img.width, img.height);
861
+ const sx = Math.floor((img.width - sl) / 2);
862
+ const sy = Math.floor((img.height - sl) / 2);
863
+
864
+ const canvas = document.createElement('canvas');
865
+ canvas.width = options.size;
866
+ canvas.height = options.size;
867
+
868
+ const ctx = canvas.getContext('2d');
869
+ ctx.drawImage(img, sx, sy, sl, sl, 0, 0, options.size, options.size);
870
+
871
+ const dataUrl = canvas.toDataURL(options.mimetype, options.quality);
872
+
873
+ if (options.asDataUrl)
874
+ return dataUrl;
875
+
876
+ return Object.assign(media, {
877
+ mimetype: options.mimetype,
878
+ data: dataUrl.replace(`data:${options.mimetype};base64,`, '')
879
+ });
880
+ };
881
+
882
+ window.WWebJS.setPicture = async (chatId, media) => {
883
+ const thumbnail = await window.WWebJS.cropAndResizeImage(media, { asDataUrl: true, mimetype: 'image/jpeg', size: 96 });
884
+ const profilePic = await window.WWebJS.cropAndResizeImage(media, { asDataUrl: true, mimetype: 'image/jpeg', size: 640 });
885
+
886
+ const chatWid = window.Store.WidFactory.createWid(chatId);
887
+ try {
888
+ const collection = window.Store.ProfilePicThumb.get(chatId) || await window.Store.ProfilePicThumb.find(chatId);
889
+ if (!collection?.canSet()) return false;
890
+
891
+ const res = await window.Store.GroupUtils.sendSetPicture(chatWid, thumbnail, profilePic);
892
+ return res ? res.status === 200 : false;
893
+ } catch (err) {
894
+ if (err.name === 'ServerStatusCodeError') return false;
895
+ throw err;
896
+ }
897
+ };
898
+
899
+ window.WWebJS.deletePicture = async (chatid) => {
900
+ const chatWid = window.Store.WidFactory.createWid(chatid);
901
+ try {
902
+ const collection = window.Store.ProfilePicThumb.get(chatid);
903
+ if (!collection.canDelete()) return;
904
+
905
+ const res = await window.Store.GroupUtils.requestDeletePicture(chatWid);
906
+ return res ? res.status === 200 : false;
907
+ } catch (err) {
908
+ if(err.name === 'ServerStatusCodeError') return false;
909
+ throw err;
910
+ }
911
+ };
912
+
913
+ window.WWebJS.getProfilePicThumbToBase64 = async (chatWid) => {
914
+ const profilePicCollection = await window.Store.ProfilePicThumb.find(chatWid);
915
+
916
+ const _readImageAsBase64 = (imageBlob) => {
917
+ return new Promise((resolve) => {
918
+ const reader = new FileReader();
919
+ reader.onloadend = function () {
920
+ const base64Image = reader.result;
921
+ if (base64Image == null) {
922
+ resolve(undefined);
923
+ } else {
924
+ const base64Data = base64Image.toString().split(',')[1];
925
+ resolve(base64Data);
926
+ }
927
+ };
928
+ reader.readAsDataURL(imageBlob);
929
+ });
930
+ };
931
+
932
+ if (profilePicCollection?.img) {
933
+ try {
934
+ const response = await fetch(profilePicCollection.img);
935
+ if (response.ok) {
936
+ const imageBlob = await response.blob();
937
+ if (imageBlob) {
938
+ const base64Image = await _readImageAsBase64(imageBlob);
939
+ return base64Image;
940
+ }
941
+ }
942
+ } catch (error) { /* empty */ }
943
+ }
944
+ return undefined;
945
+ };
946
+
947
+ window.WWebJS.getAddParticipantsRpcResult = async (groupWid, participantWid) => {
948
+ const iqTo = window.Store.WidToJid.widToGroupJid(groupWid);
949
+
950
+ const participantArgs = [{
951
+ participantJid: window.Store.WidToJid.widToUserJid(participantWid)
952
+ }];
953
+
954
+ let rpcResult, resultArgs;
955
+ const data = {
956
+ name: undefined,
957
+ code: undefined,
958
+ inviteV4Code: undefined,
959
+ inviteV4CodeExp: undefined
960
+ };
961
+
962
+ try {
963
+ rpcResult = await window.Store.GroupParticipants.sendAddParticipantsRPC({ participantArgs, iqTo });
964
+ resultArgs = rpcResult.value.addParticipant[0]
965
+ .addParticipantsParticipantAddedOrNonRegisteredWaUserParticipantErrorLidResponseMixinGroup
966
+ .value
967
+ .addParticipantsParticipantMixins;
968
+ } catch (err) {
969
+ data.code = 400;
970
+ return data;
971
+ }
972
+
973
+ if (rpcResult.name === 'AddParticipantsResponseSuccess') {
974
+ const code = resultArgs?.value.error || '200';
975
+ data.name = resultArgs?.name;
976
+ data.code = +code;
977
+ data.inviteV4Code = resultArgs?.value.addRequestCode;
978
+ data.inviteV4CodeExp = resultArgs?.value.addRequestExpiration?.toString();
979
+ }
980
+
981
+ else if (rpcResult.name === 'AddParticipantsResponseClientError') {
982
+ const { code: code } = rpcResult.value.errorAddParticipantsClientErrors.value;
983
+ data.code = +code;
984
+ }
985
+
986
+ else if (rpcResult.name === 'AddParticipantsResponseServerError') {
987
+ const { code: code } = rpcResult.value.errorServerErrors.value;
988
+ data.code = +code;
989
+ }
990
+
991
+ return data;
992
+ };
993
+
994
+ window.WWebJS.membershipRequestAction = async (groupId, action, requesterIds, sleep) => {
995
+ const groupWid = window.Store.WidFactory.createWid(groupId);
996
+ const group = await window.Store.Chat.find(groupWid);
997
+ const toApprove = action === 'Approve';
998
+ let membershipRequests;
999
+ let response;
1000
+ let result = [];
1001
+
1002
+ await window.Store.GroupQueryAndUpdate({ id: groupId });
1003
+
1004
+ if (!requesterIds?.length) {
1005
+ membershipRequests = group.groupMetadata.membershipApprovalRequests._models.map(({ id }) => id);
1006
+ } else {
1007
+ !Array.isArray(requesterIds) && (requesterIds = [requesterIds]);
1008
+ membershipRequests = requesterIds.map(r => window.Store.WidFactory.createWid(r));
1009
+ }
1010
+
1011
+ if (!membershipRequests.length) return [];
1012
+
1013
+ const participantArgs = membershipRequests.map(m => ({
1014
+ participantArgs: [
1015
+ {
1016
+ participantJid: window.Store.WidToJid.widToUserJid(m)
1017
+ }
1018
+ ]
1019
+ }));
1020
+
1021
+ const groupJid = window.Store.WidToJid.widToGroupJid(groupWid);
1022
+
1023
+ const _getSleepTime = (sleep) => {
1024
+ if (!Array.isArray(sleep) || (sleep.length === 2 && sleep[0] === sleep[1])) {
1025
+ return sleep;
1026
+ }
1027
+ if (sleep.length === 1) {
1028
+ return sleep[0];
1029
+ }
1030
+ sleep[1] - sleep[0] < 100 && (sleep[0] = sleep[1]) && (sleep[1] += 100);
1031
+ return Math.floor(Math.random() * (sleep[1] - sleep[0] + 1)) + sleep[0];
1032
+ };
1033
+
1034
+ const membReqResCodes = {
1035
+ default: `An unknown error occupied while ${toApprove ? 'approving' : 'rejecting'} the participant membership request`,
1036
+ 400: 'ParticipantNotFoundError',
1037
+ 401: 'ParticipantNotAuthorizedError',
1038
+ 403: 'ParticipantForbiddenError',
1039
+ 404: 'ParticipantRequestNotFoundError',
1040
+ 408: 'ParticipantTemporarilyBlockedError',
1041
+ 409: 'ParticipantConflictError',
1042
+ 412: 'ParticipantParentLinkedGroupsResourceConstraintError',
1043
+ 500: 'ParticipantResourceConstraintError'
1044
+ };
1045
+
1046
+ try {
1047
+ for (const participant of participantArgs) {
1048
+ response = await window.Store.MembershipRequestUtils.sendMembershipRequestsActionRPC({
1049
+ iqTo: groupJid,
1050
+ [toApprove ? 'approveArgs' : 'rejectArgs']: participant
1051
+ });
1052
+
1053
+ if (response.name === 'MembershipRequestsActionResponseSuccess') {
1054
+ const value = toApprove
1055
+ ? response.value.membershipRequestsActionApprove
1056
+ : response.value.membershipRequestsActionReject;
1057
+ if (value?.participant) {
1058
+ const [_] = value.participant.map(p => {
1059
+ const error = toApprove
1060
+ ? value.participant[0].membershipRequestsActionAcceptParticipantMixins?.value.error
1061
+ : value.participant[0].membershipRequestsActionRejectParticipantMixins?.value.error;
1062
+ return {
1063
+ requesterId: window.Store.WidFactory.createWid(p.jid)._serialized,
1064
+ ...(error
1065
+ ? { error: +error, message: membReqResCodes[error] || membReqResCodes.default }
1066
+ : { message: `${toApprove ? 'Approved' : 'Rejected'} successfully` })
1067
+ };
1068
+ });
1069
+ _ && result.push(_);
1070
+ }
1071
+ } else {
1072
+ result.push({
1073
+ requesterId: window.Store.JidToWid.userJidToUserWid(participant.participantArgs[0].participantJid)._serialized,
1074
+ message: 'ServerStatusCodeError'
1075
+ });
1076
+ }
1077
+
1078
+ sleep &&
1079
+ participantArgs.length > 1 &&
1080
+ participantArgs.indexOf(participant) !== participantArgs.length - 1 &&
1081
+ (await new Promise((resolve) => setTimeout(resolve, _getSleepTime(sleep))));
1082
+ }
1083
+ return result;
1084
+ } catch (err) {
1085
+ return [];
1086
+ }
1087
+ };
1088
+
1089
+ window.WWebJS.subscribeToUnsubscribeFromChannel = async (channelId, action, options = {}) => {
1090
+ const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
1091
+
1092
+ if (!channel || channel.newsletterMetadata.membershipType === 'owner') return false;
1093
+ options = { eventSurface: 3, deleteLocalModels: options.deleteLocalModels ?? true };
1094
+
1095
+ try {
1096
+ if (action === 'Subscribe') {
1097
+ await window.Store.ChannelUtils.subscribeToNewsletterAction(channel, options);
1098
+ } else if (action === 'Unsubscribe') {
1099
+ await window.Store.ChannelUtils.unsubscribeFromNewsletterAction(channel, options);
1100
+ } else return false;
1101
+ return true;
1102
+ } catch (err) {
1103
+ if (err.name === 'ServerStatusCodeError') return false;
1104
+ throw err;
1105
+ }
1106
+ };
1107
+
1108
+ window.WWebJS.pinUnpinMsgAction = async (msgId, action, duration) => {
1109
+ const message = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
1110
+ if (!message) return false;
1111
+
1112
+ if (typeof duration !== 'number') return false;
1113
+
1114
+ const originalFunction = window.require('WAWebPinMsgConstants').getPinExpiryDuration;
1115
+ window.require('WAWebPinMsgConstants').getPinExpiryDuration = () => duration;
1116
+
1117
+ const response = await window.Store.PinnedMsgUtils.sendPinInChatMsg(message, action, duration);
1118
+
1119
+ window.require('WAWebPinMsgConstants').getPinExpiryDuration = originalFunction;
1120
+
1121
+ return response.messageSendResult === 'OK';
1122
+ };
1123
+
1124
+ window.WWebJS.getStatusModel = status => {
1125
+ const res = status.serialize();
1126
+ delete res._msgs;
1127
+ return res;
1128
+ };
1129
+
1130
+ window.WWebJS.getAllStatuses = () => {
1131
+ const statuses = window.Store.Status.getModelsArray();
1132
+ return statuses.map(status => window.WWebJS.getStatusModel(status));
1133
+ };
1134
+
1135
+ window.WWebJS.enforceLidAndPnRetrieval = async (userId) => {
1136
+ const wid = window.Store.WidFactory.createWid(userId);
1137
+ const isLid = wid.server === 'lid';
1138
+
1139
+ let lid = isLid ? wid : window.Store.LidUtils.getCurrentLid(wid);
1140
+ let phone = isLid ? window.Store.LidUtils.getPhoneNumber(wid) : wid;
1141
+
1142
+ if (!isLid && !lid) {
1143
+ const queryResult = await window.Store.QueryExist(wid);
1144
+ if (!queryResult?.wid) return {};
1145
+ lid = window.Store.LidUtils.getCurrentLid(wid);
1146
+ }
1147
+
1148
+ if (isLid && !phone) {
1149
+ const queryResult = await window.Store.QueryExist(wid);
1150
+ if (!queryResult?.wid) return {};
1151
+ phone = window.Store.LidUtils.getPhoneNumber(wid);
1152
+ }
1153
+
1154
+ return { lid, phone };
1155
+ };
1156
+ };