whatsapp-web.js 1.28.0 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,60 +5,61 @@ exports.LoadUtils = () => {
5
5
 
6
6
  window.WWebJS.forwardMessage = async (chatId, msgId) => {
7
7
  const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
8
- let chat = window.Store.Chat.get(chatId);
8
+ const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
9
9
 
10
10
  if (window.compareWwebVersions(window.Debug.VERSION, '>', '2.3000.0')) {
11
- return window.Store.ForwardUtils.forwardMessagesToChats([msg], [chat], false);
11
+ return window.Store.ForwardUtils.forwardMessagesToChats([msg], [chat], true);
12
12
  } else {
13
13
  return chat.forwardMessages([msg]);
14
14
  }
15
15
  };
16
16
 
17
17
  window.WWebJS.sendSeen = async (chatId) => {
18
- let chat = window.Store.Chat.get(chatId);
19
- if (chat !== undefined) {
20
- await window.Store.SendSeen.sendSeen(chat, false);
18
+ const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
19
+ if (chat) {
20
+ await window.Store.SendSeen.sendSeen(chat);
21
21
  return true;
22
22
  }
23
23
  return false;
24
-
25
24
  };
26
25
 
27
26
  window.WWebJS.sendMessage = async (chat, content, options = {}) => {
28
- let attOptions = {};
29
- if (options.attachment) {
30
- attOptions = options.sendMediaAsSticker
31
- ? await window.WWebJS.processStickerData(options.attachment)
32
- : await window.WWebJS.processMediaData(options.attachment, {
27
+ const isChannel = window.Store.ChatGetters.getIsNewsletter(chat);
28
+
29
+ let mediaOptions = {};
30
+ if (options.media) {
31
+ mediaOptions = await window.WWebJS.processMediaData(
32
+ options.media, {
33
+ forceSticker: options.sendMediaAsSticker,
34
+ forceGif: options.sendVideoAsGif,
33
35
  forceVoice: options.sendAudioAsVoice,
34
36
  forceDocument: options.sendMediaAsDocument,
35
- forceGif: options.sendVideoAsGif
37
+ sendToChannel: isChannel
36
38
  });
37
-
38
- attOptions.caption = options.caption;
39
- content = options.sendMediaAsSticker ? undefined : attOptions.preview;
40
- attOptions.isViewOnce = options.isViewOnce;
41
-
42
- delete options.attachment;
39
+ mediaOptions.caption = options.caption;
40
+ content = options.sendMediaAsSticker ? undefined : mediaOptions.preview;
41
+ mediaOptions.isViewOnce = options.isViewOnce;
42
+ delete options.media;
43
43
  delete options.sendMediaAsSticker;
44
44
  }
45
+
45
46
  let quotedMsgOptions = {};
46
47
  if (options.quotedMessageId) {
47
- let quotedMessage = await window.Store.Msg.getMessagesById([options.quotedMessageId]);
48
+ let quotedMessage = window.Store.Msg.get(options.quotedMessageId);
49
+ !quotedMessage && (quotedMessage = (await window.Store.Msg.getMessagesById([options.quotedMessageId]))?.messages?.[0]);
48
50
 
49
51
  if (quotedMessage['messages'].length == 1) {
50
52
  quotedMessage = quotedMessage['messages'][0];
51
53
 
52
- // TODO remove .canReply() once all clients are updated to >= v2.2241.6
53
- const canReply = window.Store.ReplyUtils ?
54
- window.Store.ReplyUtils.canReplyMsg(quotedMessage.unsafe()) :
55
- quotedMessage.canReply();
54
+ const canReply = window.Store.ReplyUtils
55
+ ? window.Store.ReplyUtils.canReplyMsg(quotedMessage.unsafe())
56
+ : quotedMessage.canReply();
56
57
 
57
58
  if (canReply) {
58
59
  quotedMsgOptions = quotedMessage.msgContextInfo(chat);
59
60
  }
60
- }else{
61
- if(!options.ignoreQuoteErrors) {
61
+ } else {
62
+ if (!options.ignoreQuoteErrors) {
62
63
  throw new Error('Could not get the quoted message.');
63
64
  }
64
65
  }
@@ -106,14 +107,15 @@ exports.LoadUtils = () => {
106
107
  const { pollName, pollOptions } = options.poll;
107
108
  const { allowMultipleAnswers, messageSecret } = options.poll.options;
108
109
  _pollOptions = {
110
+ kind: 'pollCreation',
109
111
  type: 'poll_creation',
110
112
  pollName: pollName,
111
113
  pollOptions: pollOptions,
112
114
  pollSelectableOptionsCount: allowMultipleAnswers ? 0 : 1,
113
115
  messageSecret:
114
- Array.isArray(messageSecret) && messageSecret.length === 32
115
- ? new Uint8Array(messageSecret)
116
- : window.crypto.getRandomValues(new Uint8Array(32))
116
+ Array.isArray(messageSecret) && messageSecret.length === 32
117
+ ? new Uint8Array(messageSecret)
118
+ : window.crypto.getRandomValues(new Uint8Array(32))
117
119
  };
118
120
  delete options.poll;
119
121
  }
@@ -164,9 +166,9 @@ exports.LoadUtils = () => {
164
166
  }
165
167
  }
166
168
  }
167
-
169
+
168
170
  let buttonOptions = {};
169
- if(options.buttons){
171
+ if (options.buttons) {
170
172
  let caption;
171
173
  if (options.buttons.type === 'chat') {
172
174
  content = options.buttons.body;
@@ -214,14 +216,22 @@ exports.LoadUtils = () => {
214
216
  delete options.invokedBotWid;
215
217
  }
216
218
 
219
+ const lidUser = window.Store.User.getMaybeMeLidUser();
217
220
  const meUser = window.Store.User.getMaybeMeUser();
218
221
  const newId = await window.Store.MsgKey.newId();
219
-
220
- const newMsgId = new window.Store.MsgKey({
221
- from: meUser,
222
+ let from = chat.id.isLid() ? lidUser : meUser;
223
+ let participant;
224
+
225
+ if (chat.isGroup) {
226
+ from = chat.groupMetadata && chat.groupMetadata.isLidAddressingMode ? lidUser : meUser;
227
+ participant = window.Store.WidFactory.toUserWid(from);
228
+ }
229
+
230
+ const newMsgKey = new window.Store.MsgKey({
231
+ from: from,
222
232
  to: chat.id,
223
233
  id: newId,
224
- participant: chat.id.isGroup() ? meUser : undefined,
234
+ participant: participant,
225
235
  selfDir: 'out',
226
236
  });
227
237
 
@@ -232,7 +242,7 @@ exports.LoadUtils = () => {
232
242
 
233
243
  const message = {
234
244
  ...options,
235
- id: newMsgId,
245
+ id: newMsgKey,
236
246
  ack: 0,
237
247
  body: content,
238
248
  from: meUser,
@@ -243,11 +253,11 @@ exports.LoadUtils = () => {
243
253
  isNewMsg: true,
244
254
  type: 'chat',
245
255
  ...ephemeralFields,
256
+ ...mediaOptions,
257
+ ...(mediaOptions.toJSON ? mediaOptions.toJSON() : {}),
258
+ ...quotedMsgOptions,
246
259
  ...locationOptions,
247
260
  ..._pollOptions,
248
- ...attOptions,
249
- ...(attOptions.toJSON ? attOptions.toJSON() : {}),
250
- ...quotedMsgOptions,
251
261
  ...vcardOptions,
252
262
  ...buttonOptions,
253
263
  ...listOptions,
@@ -260,12 +270,41 @@ exports.LoadUtils = () => {
260
270
  delete message.canonicalUrl;
261
271
  }
262
272
 
273
+ if (isChannel) {
274
+ const msg = new window.Store.Msg.modelClass(message);
275
+ const msgDataFromMsgModel = window.Store.SendChannelMessage.msgDataFromMsgModel(msg);
276
+ const isMedia = Object.keys(mediaOptions).length > 0;
277
+ await window.Store.SendChannelMessage.addNewsletterMsgsRecords([msgDataFromMsgModel]);
278
+ chat.msgs.add(msg);
279
+ chat.t = msg.t;
280
+
281
+ const sendChannelMsgResponse = await window.Store.SendChannelMessage.sendNewsletterMessageJob({
282
+ msg: msg,
283
+ type: message.type === 'chat' ? 'text' : isMedia ? 'media' : 'pollCreation',
284
+ newsletterJid: chat.id.toJid(),
285
+ ...(isMedia
286
+ ? {
287
+ mediaMetadata: msg.avParams(),
288
+ mediaHandle: isMedia ? mediaOptions.mediaHandle : null,
289
+ }
290
+ : {}
291
+ )
292
+ });
293
+
294
+ if (sendChannelMsgResponse.success) {
295
+ msg.t = sendChannelMsgResponse.ack.t;
296
+ msg.serverId = sendChannelMsgResponse.serverId;
297
+ }
298
+ msg.updateAck(1, true);
299
+ await window.Store.SendChannelMessage.updateNewsletterMsgRecord(msg);
300
+ return msg;
301
+ }
302
+
263
303
  await window.Store.SendMessage.addAndSendMsgToChat(chat, message);
264
- return window.Store.Msg.get(newMsgId._serialized);
304
+ return window.Store.Msg.get(newMsgKey._serialized);
265
305
  };
266
306
 
267
307
  window.WWebJS.editMessage = async (msg, content, options = {}) => {
268
-
269
308
  const extraOptions = options.extraOptions || {};
270
309
  delete options.extraOptions;
271
310
 
@@ -323,74 +362,51 @@ exports.LoadUtils = () => {
323
362
  };
324
363
  };
325
364
 
326
- window.WWebJS.processStickerData = async (mediaInfo) => {
327
- if (mediaInfo.mimetype !== 'image/webp') throw new Error('Invalid media type');
328
-
329
- const file = window.WWebJS.mediaInfoToFile(mediaInfo);
330
- let filehash = await window.WWebJS.getFileHash(file);
331
- let mediaKey = await window.WWebJS.generateHash(32);
332
-
333
- const controller = new AbortController();
334
- const uploadedInfo = await window.Store.UploadUtils.encryptAndUpload({
335
- blob: file,
336
- type: 'sticker',
337
- signal: controller.signal,
338
- mediaKey
339
- });
340
-
341
- const stickerInfo = {
342
- ...uploadedInfo,
343
- clientUrl: uploadedInfo.url,
344
- deprecatedMms3Url: uploadedInfo.url,
345
- uploadhash: uploadedInfo.encFilehash,
346
- size: file.size,
347
- type: 'sticker',
348
- filehash
349
- };
350
-
351
- return stickerInfo;
352
- };
353
-
354
- window.WWebJS.processMediaData = async (mediaInfo, { forceVoice, forceDocument, forceGif }) => {
365
+ window.WWebJS.processMediaData = async (mediaInfo, { forceSticker, forceGif, forceVoice, forceDocument, sendToChannel }) => {
355
366
  const file = window.WWebJS.mediaInfoToFile(mediaInfo);
356
- const mData = await window.Store.OpaqueData.createFromData(file, file.type);
357
- const mediaPrep = window.Store.MediaPrep.prepRawMedia(mData, { asDocument: forceDocument });
367
+ const opaqueData = await window.Store.OpaqueData.createFromData(file, file.type);
368
+ const mediaPrep = window.Store.MediaPrep.prepRawMedia(
369
+ opaqueData, {
370
+ asSticker: forceSticker,
371
+ asGif: forceGif,
372
+ isPtt: forceVoice,
373
+ asDocument: forceDocument
374
+ });
358
375
  const mediaData = await mediaPrep.waitForPrep();
359
376
  const mediaObject = window.Store.MediaObject.getOrCreateMediaObject(mediaData.filehash);
360
-
361
377
  const mediaType = window.Store.MediaTypes.msgToMediaType({
362
378
  type: mediaData.type,
363
- isGif: mediaData.isGif
379
+ isGif: mediaData.isGif,
380
+ isNewsletter: sendToChannel,
364
381
  });
365
382
 
366
- if (forceVoice && mediaData.type === 'audio') {
367
- mediaData.type = 'ptt';
383
+ if (forceVoice && mediaData.type === 'ptt') {
368
384
  const waveform = mediaObject.contentInfo.waveform;
369
385
  mediaData.waveform =
370
- waveform ?? await window.WWebJS.generateWaveform(file);
371
- }
372
-
373
- if (forceGif && mediaData.type === 'video') {
374
- mediaData.isGif = true;
375
- }
376
-
377
- if (forceDocument) {
378
- mediaData.type = 'document';
386
+ waveform || await window.WWebJS.generateWaveform(file);
379
387
  }
380
388
 
381
389
  if (!(mediaData.mediaBlob instanceof window.Store.OpaqueData)) {
382
- mediaData.mediaBlob = await window.Store.OpaqueData.createFromData(mediaData.mediaBlob, mediaData.mediaBlob.type);
390
+ mediaData.mediaBlob = await window.Store.OpaqueData.createFromData(
391
+ mediaData.mediaBlob,
392
+ mediaData.mediaBlob.type
393
+ );
383
394
  }
384
395
 
385
396
  mediaData.renderableUrl = mediaData.mediaBlob.url();
386
397
  mediaObject.consolidate(mediaData.toJSON());
387
398
  mediaData.mediaBlob.autorelease();
388
399
 
389
- const uploadedMedia = await window.Store.MediaUpload.uploadMedia({
400
+ const dataToUpload = {
390
401
  mimetype: mediaData.mimetype,
391
402
  mediaObject,
392
- mediaType
393
- });
403
+ mediaType,
404
+ ...(sendToChannel ? { calculateToken: window.Store.SendChannelMessage.getRandomFilehash } : {})
405
+ };
406
+
407
+ const uploadedMedia = !sendToChannel
408
+ ? await window.Store.MediaUpload.uploadMedia(dataToUpload)
409
+ : await window.Store.MediaUpload.uploadUnencryptedMedia(dataToUpload);
394
410
 
395
411
  const mediaEntry = uploadedMedia.mediaEntry;
396
412
  if (!mediaEntry) {
@@ -408,13 +424,14 @@ exports.LoadUtils = () => {
408
424
  uploadhash: mediaEntry.uploadHash,
409
425
  size: mediaObject.size,
410
426
  streamingSidecar: mediaEntry.sidecar,
411
- firstFrameSidecar: mediaEntry.firstFrameSidecar
427
+ firstFrameSidecar: mediaEntry.firstFrameSidecar,
428
+ mediaHandle: sendToChannel ? mediaEntry.handle : null,
412
429
  });
413
430
 
414
431
  return mediaData;
415
432
  };
416
433
 
417
- window.WWebJS.getMessageModel = message => {
434
+ window.WWebJS.getMessageModel = (message) => {
418
435
  const msg = message.serialize();
419
436
 
420
437
  msg.isEphemeral = message.isEphemeral;
@@ -452,50 +469,115 @@ exports.LoadUtils = () => {
452
469
  return _vote;
453
470
  };
454
471
 
455
- window.WWebJS.getChatModel = async chat => {
456
-
457
- let res = chat.serialize();
458
- res.isGroup = false;
459
- res.formattedTitle = chat.formattedTitle;
460
- res.isMuted = chat.muteExpiration == 0 ? false : true;
472
+ window.WWebJS.getChat = async (chatId, { getAsModel = true } = {}) => {
473
+ const isChannel = /@\w*newsletter\b/.test(chatId);
474
+ const chatWid = window.Store.WidFactory.createWid(chatId);
475
+ let chat;
461
476
 
462
- if (chat.groupMetadata) {
463
- res.isGroup = true;
464
- const chatWid = window.Store.WidFactory.createWid((chat.id._serialized));
465
- await window.Store.GroupMetadata.update(chatWid);
466
- res.groupMetadata = chat.groupMetadata.serialize();
467
- }
468
-
469
- res.lastMessage = null;
470
- if (res.msgs && res.msgs.length) {
471
- const lastMessage = chat.lastReceivedKey
472
- ? window.Store.Msg.get(chat.lastReceivedKey._serialized) || (await window.Store.Msg.getMessagesById([chat.lastReceivedKey._serialized]))?.messages?.[0]
473
- : null;
474
- if (lastMessage) {
475
- res.lastMessage = window.WWebJS.getMessageModel(lastMessage);
477
+ if (isChannel) {
478
+ try {
479
+ chat = window.Store.NewsletterCollection.get(chatId);
480
+ if (!chat) {
481
+ await window.Store.ChannelUtils.loadNewsletterPreviewChat(chatId);
482
+ chat = await window.Store.NewsletterCollection.find(chatWid);
483
+ }
484
+ } catch (err) {
485
+ chat = null;
476
486
  }
487
+ } else {
488
+ chat = window.Store.Chat.get(chatWid) || (await window.Store.Chat.find(chatWid));
477
489
  }
478
-
479
- delete res.msgs;
480
- delete res.msgUnsyncedButtonReplyMsgs;
481
- delete res.unsyncedButtonReplies;
482
490
 
483
- return res;
491
+ return getAsModel && chat
492
+ ? await window.WWebJS.getChatModel(chat, { isChannel: isChannel })
493
+ : chat;
484
494
  };
485
495
 
486
- window.WWebJS.getChat = async chatId => {
487
- const chatWid = window.Store.WidFactory.createWid(chatId);
488
- const chat = await window.Store.Chat.find(chatWid);
489
- return await window.WWebJS.getChatModel(chat);
496
+ window.WWebJS.getChannelMetadata = async (inviteCode) => {
497
+ const response =
498
+ await window.Store.ChannelUtils.queryNewsletterMetadataByInviteCode(
499
+ inviteCode,
500
+ window.Store.ChannelUtils.getRoleByIdentifier(inviteCode)
501
+ );
502
+
503
+ const picUrl = response.newsletterPictureMetadataMixin?.picture[0]?.queryPictureDirectPathOrEmptyResponseMixinGroup.value.directPath;
504
+
505
+ return {
506
+ id: response.idJid,
507
+ createdAtTs: response.newsletterCreationTimeMetadataMixin.creationTimeValue,
508
+ titleMetadata: {
509
+ title: response.newsletterNameMetadataMixin.nameElementValue,
510
+ updatedAtTs: response.newsletterNameMetadataMixin.nameUpdateTime
511
+ },
512
+ descriptionMetadata: {
513
+ description: response.newsletterDescriptionMetadataMixin.descriptionQueryDescriptionResponseMixin.elementValue,
514
+ updatedAtTs: response.newsletterDescriptionMetadataMixin.descriptionQueryDescriptionResponseMixin.updateTime
515
+ },
516
+ inviteLink: `https://whatsapp.com/channel/${response.newsletterInviteLinkMetadataMixin.inviteCode}`,
517
+ membershipType: window.Store.ChannelUtils.getRoleByIdentifier(inviteCode),
518
+ stateType: response.newsletterStateMetadataMixin.stateType,
519
+ pictureUrl: picUrl ? `https://pps.whatsapp.net${picUrl}` : null,
520
+ subscribersCount: response.newsletterSubscribersMetadataMixin.subscribersCount,
521
+ isVerified: response.newsletterVerificationMetadataMixin.verificationState === 'verified'
522
+ };
490
523
  };
491
524
 
492
525
  window.WWebJS.getChats = async () => {
493
526
  const chats = window.Store.Chat.getModelsArray();
494
-
495
527
  const chatPromises = chats.map(chat => window.WWebJS.getChatModel(chat));
496
528
  return await Promise.all(chatPromises);
497
529
  };
498
530
 
531
+ window.WWebJS.getChannels = async () => {
532
+ const channels = window.Store.NewsletterCollection.getModelsArray();
533
+ const channelPromises = channels?.map((channel) => window.WWebJS.getChatModel(channel, { isChannel: true }));
534
+ return await Promise.all(channelPromises);
535
+ };
536
+
537
+ window.WWebJS.getChatModel = async (chat, { isChannel = false } = {}) => {
538
+ if (!chat) return null;
539
+
540
+ const model = chat.serialize();
541
+ model.isGroup = false;
542
+ model.isMuted = chat.mute?.expiration !== 0;
543
+ if (isChannel) {
544
+ model.isChannel = window.Store.ChatGetters.getIsNewsletter(chat);
545
+ } else {
546
+ model.formattedTitle = chat.formattedTitle;
547
+ }
548
+
549
+ if (chat.groupMetadata) {
550
+ model.isGroup = true;
551
+ const chatWid = window.Store.WidFactory.createWid(chat.id._serialized);
552
+ await window.Store.GroupMetadata.update(chatWid);
553
+ model.groupMetadata.participants._models
554
+ .filter(x => x.id._serialized.endsWith('@lid'))
555
+ .forEach(x => { x.id = x.contact.phoneNumber; });
556
+ model.groupMetadata = chat.groupMetadata.serialize();
557
+ model.isReadOnly = chat.groupMetadata.announce;
558
+ }
559
+
560
+ if (chat.newsletterMetadata) {
561
+ await window.Store.NewsletterMetadataCollection.update(chat.id);
562
+ model.channelMetadata = chat.newsletterMetadata.serialize();
563
+ model.channelMetadata.createdAtTs = chat.newsletterMetadata.creationTime;
564
+ }
565
+
566
+ model.lastMessage = null;
567
+ if (model.msgs && model.msgs.length) {
568
+ const lastMessage = chat.lastReceivedKey
569
+ ? window.Store.Msg.get(chat.lastReceivedKey._serialized) || (await window.Store.Msg.getMessagesById([chat.lastReceivedKey._serialized]))?.messages?.[0]
570
+ : null;
571
+ lastMessage && (model.lastMessage = window.WWebJS.getMessageModel(lastMessage));
572
+ }
573
+
574
+ delete model.msgs;
575
+ delete model.msgUnsyncedButtonReplyMsgs;
576
+ delete model.unsyncedButtonReplies;
577
+
578
+ return model;
579
+ };
580
+
499
581
  window.WWebJS.getContactModel = contact => {
500
582
  let res = contact.serialize();
501
583
  res.isBusiness = contact.isBusiness === undefined ? false : contact.isBusiness;
@@ -504,57 +586,30 @@ exports.LoadUtils = () => {
504
586
  res.businessProfile = contact.businessProfile.serialize();
505
587
  }
506
588
 
507
- // TODO: remove useOldImplementation and its checks once all clients are updated to >= v2.2327.4
508
- const useOldImplementation
509
- = window.compareWwebVersions(window.Debug.VERSION, '<', '2.2327.4');
510
-
511
- res.isMe = useOldImplementation
512
- ? contact.isMe
513
- : window.Store.ContactMethods.getIsMe(contact);
514
- res.isUser = useOldImplementation
515
- ? contact.isUser
516
- : window.Store.ContactMethods.getIsUser(contact);
517
- res.isGroup = useOldImplementation
518
- ? contact.isGroup
519
- : window.Store.ContactMethods.getIsGroup(contact);
520
- res.isWAContact = useOldImplementation
521
- ? contact.isWAContact
522
- : window.Store.ContactMethods.getIsWAContact(contact);
523
- res.isMyContact = useOldImplementation
524
- ? contact.isMyContact
525
- : window.Store.ContactMethods.getIsMyContact(contact);
589
+ res.isMe = window.Store.ContactMethods.getIsMe(contact);
590
+ res.isUser = window.Store.ContactMethods.getIsUser(contact);
591
+ res.isGroup = window.Store.ContactMethods.getIsGroup(contact);
592
+ res.isWAContact = window.Store.ContactMethods.getIsWAContact(contact);
593
+ res.isMyContact = window.Store.ContactMethods.getIsMyContact(contact);
526
594
  res.isBlocked = contact.isContactBlocked;
527
- res.userid = useOldImplementation
528
- ? contact.userid
529
- : window.Store.ContactMethods.getUserid(contact);
530
- res.isEnterprise = useOldImplementation
531
- ? contact.isEnterprise
532
- : window.Store.ContactMethods.getIsEnterprise(contact);
533
- res.verifiedName = useOldImplementation
534
- ? contact.verifiedName
535
- : window.Store.ContactMethods.getVerifiedName(contact);
536
- res.verifiedLevel = useOldImplementation
537
- ? contact.verifiedLevel
538
- : window.Store.ContactMethods.getVerifiedLevel(contact);
539
- res.statusMute = useOldImplementation
540
- ? contact.statusMute
541
- : window.Store.ContactMethods.getStatusMute(contact);
542
- res.name = useOldImplementation
543
- ? contact.name
544
- : window.Store.ContactMethods.getName(contact);
545
- res.shortName = useOldImplementation
546
- ? contact.shortName
547
- : window.Store.ContactMethods.getShortName(contact);
548
- res.pushname = useOldImplementation
549
- ? contact.pushname
550
- : window.Store.ContactMethods.getPushname(contact);
595
+ res.userid = window.Store.ContactMethods.getUserid(contact);
596
+ res.isEnterprise = window.Store.ContactMethods.getIsEnterprise(contact);
597
+ res.verifiedName = window.Store.ContactMethods.getVerifiedName(contact);
598
+ res.verifiedLevel = window.Store.ContactMethods.getVerifiedLevel(contact);
599
+ res.statusMute = window.Store.ContactMethods.getStatusMute(contact);
600
+ res.name = window.Store.ContactMethods.getName(contact);
601
+ res.shortName = window.Store.ContactMethods.getShortName(contact);
602
+ res.pushname = window.Store.ContactMethods.getPushname(contact);
551
603
 
552
604
  return res;
553
605
  };
554
606
 
555
607
  window.WWebJS.getContact = async contactId => {
556
608
  const wid = window.Store.WidFactory.createWid(contactId);
557
- const contact = await window.Store.Contact.find(wid);
609
+ let contact = await window.Store.Contact.find(wid);
610
+ if (contact.id._serialized.endsWith('@lid')) {
611
+ contact.id = contact.phoneNumber;
612
+ }
558
613
  const bizProfile = await window.Store.BusinessProfile.fetchBizProfile(wid);
559
614
  bizProfile.profileOptions && (contact.businessProfile = bizProfile);
560
615
  return window.WWebJS.getContactModel(contact);
@@ -621,10 +676,6 @@ exports.LoadUtils = () => {
621
676
  return result;
622
677
  };
623
678
 
624
- /**
625
- * Referenced from and modified:
626
- * @see https://github.com/wppconnect-team/wa-js/commit/290ebfefe6021b3d17f7fdfdda5545bb0473b26f
627
- */
628
679
  window.WWebJS.generateWaveform = async (audioFile) => {
629
680
  try {
630
681
  const audioData = await audioFile.arrayBuffer();
@@ -658,7 +709,7 @@ exports.LoadUtils = () => {
658
709
  };
659
710
 
660
711
  window.WWebJS.sendClearChat = async (chatId) => {
661
- let chat = window.Store.Chat.get(chatId);
712
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
662
713
  if (chat !== undefined) {
663
714
  await window.Store.SendClear.sendClear(chat, false);
664
715
  return true;
@@ -667,7 +718,7 @@ exports.LoadUtils = () => {
667
718
  };
668
719
 
669
720
  window.WWebJS.sendDeleteChat = async (chatId) => {
670
- let chat = window.Store.Chat.get(chatId);
721
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
671
722
  if (chat !== undefined) {
672
723
  await window.Store.SendDelete.sendDelete(chat);
673
724
  return true;
@@ -897,7 +948,7 @@ exports.LoadUtils = () => {
897
948
  }
898
949
 
899
950
  if (rpcResult.name === 'AddParticipantsResponseSuccess') {
900
- const code = resultArgs?.value.error ?? '200';
951
+ const code = resultArgs?.value.error || '200';
901
952
  data.name = resultArgs?.name;
902
953
  data.code = +code;
903
954
  data.inviteV4Code = resultArgs?.value.addRequestCode;
@@ -1012,6 +1063,25 @@ exports.LoadUtils = () => {
1012
1063
  }
1013
1064
  };
1014
1065
 
1066
+ window.WWebJS.subscribeToUnsubscribeFromChannel = async (channelId, action, options = {}) => {
1067
+ const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
1068
+
1069
+ if (!channel || channel.newsletterMetadata.membershipType === 'owner') return false;
1070
+ options = { eventSurface: 3, deleteLocalModels: options.deleteLocalModels ?? true };
1071
+
1072
+ try {
1073
+ if (action === 'Subscribe') {
1074
+ await window.Store.ChannelUtils.subscribeToNewsletterAction(channel, options);
1075
+ } else if (action === 'Unsubscribe') {
1076
+ await window.Store.ChannelUtils.unsubscribeFromNewsletterAction(channel, options);
1077
+ } else return false;
1078
+ return true;
1079
+ } catch (err) {
1080
+ if (err.name === 'ServerStatusCodeError') return false;
1081
+ throw err;
1082
+ }
1083
+ };
1084
+
1015
1085
  window.WWebJS.pinUnpinMsgAction = async (msgId, action, duration) => {
1016
1086
  const message = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
1017
1087
  if (!message) return false;
@@ -1020,9 +1090,8 @@ exports.LoadUtils = () => {
1020
1090
  };
1021
1091
 
1022
1092
  window.WWebJS.getStatusModel = status => {
1023
- let res = status.serialize();
1093
+ const res = status.serialize();
1024
1094
  delete res._msgs;
1025
- res.msgs = status._msgs.map(msg => window.WWebJS.getMessageModel(msg));
1026
1095
  return res;
1027
1096
  };
1028
1097
 
@@ -14,9 +14,8 @@ class InterfaceController {
14
14
  * @param {string} chatId ID of the chat window that will be opened
15
15
  */
16
16
  async openChatWindow(chatId) {
17
- await this.pupPage.evaluate(async chatId => {
18
- const chatWid = window.Store.WidFactory.createWid(chatId);
19
- const chat = window.Store.Chat.get(chatWid) || await window.Store.Chat.find(chatWid);
17
+ await this.pupPage.evaluate(async (chatId) => {
18
+ const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
20
19
  await window.Store.Cmd.openChatBottom(chat);
21
20
  }, chatId);
22
21
  }
@@ -27,7 +26,7 @@ class InterfaceController {
27
26
  */
28
27
  async openChatDrawer(chatId) {
29
28
  await this.pupPage.evaluate(async chatId => {
30
- let chat = await window.Store.Chat.get(chatId);
29
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
31
30
  await window.Store.Cmd.openDrawerMid(chat);
32
31
  }, chatId);
33
32
  }
@@ -38,7 +37,7 @@ class InterfaceController {
38
37
  */
39
38
  async openChatSearch(chatId) {
40
39
  await this.pupPage.evaluate(async chatId => {
41
- let chat = await window.Store.Chat.get(chatId);
40
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
42
41
  await window.Store.Cmd.chatSearch(chat);
43
42
  }, chatId);
44
43
  }
@@ -48,11 +47,11 @@ class InterfaceController {
48
47
  * @param {string} msgId ID of the message that will be scrolled to
49
48
  */
50
49
  async openChatWindowAt(msgId) {
51
- await this.pupPage.evaluate(async msgId => {
50
+ await this.pupPage.evaluate(async (msgId) => {
52
51
  const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
53
- let chat = await window.Store.Chat.find(msg.id.remote);
54
- let searchContext = await window.Store.SearchContext(chat,msg);
55
- await window.Store.Cmd.openChatAt(chat, searchContext);
52
+ const chat = window.Store.Chat.get(msg.id.remote) ?? await window.Store.Chat.find(msg.id.remote);
53
+ const searchContext = await window.Store.SearchContext.getSearchContext(chat, msg.id);
54
+ await window.Store.Cmd.openChatAt({ chat: chat, msgContext: searchContext });
56
55
  }, msgId);
57
56
  }
58
57