whatsapp-web.js 1.28.1-alpha.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.
package/src/Client.js CHANGED
@@ -15,7 +15,7 @@ const { LoadUtils } = require('./util/Injected/Utils');
15
15
  const ChatFactory = require('./factories/ChatFactory');
16
16
  const ContactFactory = require('./factories/ContactFactory');
17
17
  const WebCacheFactory = require('./webCache/WebCacheFactory');
18
- const { ClientInfo, Message, MessageMedia, Contact, Location, Poll, PollVote, GroupNotification, Label, Call, Buttons, List, Reaction, Broadcast} = require('./structures');
18
+ const { Broadcast, Buttons, Call, ClientInfo, Contact, GroupNotification, Label, List, Location, Message, MessageMedia, Poll, PollVote, Reaction } = require('./structures');
19
19
  const NoAuth = require('./authStrategies/NoAuth');
20
20
  const {exposeFunctionIfAbsent} = require('./util/Puppeteer');
21
21
 
@@ -820,11 +820,9 @@ class Client extends EventEmitter {
820
820
  *
821
821
  */
822
822
  async sendSeen(chatId) {
823
- const result = await this.pupPage.evaluate(async (chatId) => {
823
+ return await this.pupPage.evaluate(async (chatId) => {
824
824
  return window.WWebJS.sendSeen(chatId);
825
-
826
825
  }, chatId);
827
- return result;
828
826
  }
829
827
 
830
828
  /**
@@ -854,6 +852,7 @@ class Client extends EventEmitter {
854
852
  * @property {string} [stickerName=undefined] - Sets the name of the sticker, (if sendMediaAsSticker is true).
855
853
  * @property {string[]} [stickerCategories=undefined] - Sets the categories of the sticker, (if sendMediaAsSticker is true). Provide emoji char array, can be null.
856
854
  * @property {MessageMedia} [media] - Media to be sent
855
+ * @property {any} [extra] - Extra options
857
856
  */
858
857
 
859
858
  /**
@@ -865,6 +864,19 @@ class Client extends EventEmitter {
865
864
  * @returns {Promise<Message>} Message that was just sent
866
865
  */
867
866
  async sendMessage(chatId, content, options = {}) {
867
+ const isChannel = /@\w*newsletter\b/.test(chatId);
868
+
869
+ if (isChannel && [
870
+ options.sendMediaAsDocument, options.quotedMessageId,
871
+ options.parseVCards, options.isViewOnce,
872
+ content instanceof Location, content instanceof Contact,
873
+ content instanceof Buttons, content instanceof List,
874
+ Array.isArray(content) && content.length > 0 && content[0] instanceof Contact
875
+ ].includes(true)) {
876
+ console.warn('The message type is currently not supported for sending in channels,\nthe supported message types are: text, image, sticker, gif, video, voice and poll.');
877
+ return null;
878
+ }
879
+
868
880
  if (options.mentions) {
869
881
  !Array.isArray(options.mentions) && (options.mentions = [options.mentions]);
870
882
  if (options.mentions.some((possiblyContact) => possiblyContact instanceof Contact)) {
@@ -874,7 +886,7 @@ class Client extends EventEmitter {
874
886
  }
875
887
 
876
888
  options.groupMentions && !Array.isArray(options.groupMentions) && (options.groupMentions = [options.groupMentions]);
877
-
889
+
878
890
  let internalOptions = {
879
891
  linkPreview: options.linkPreview === false ? undefined : true,
880
892
  sendAudioAsVoice: options.sendAudioAsVoice,
@@ -890,14 +902,14 @@ class Client extends EventEmitter {
890
902
  extraOptions: options.extra
891
903
  };
892
904
 
893
- const sendSeen = typeof options.sendSeen === 'undefined' ? true : options.sendSeen;
905
+ const sendSeen = options.sendSeen !== false;
894
906
 
895
907
  if (content instanceof MessageMedia) {
896
- internalOptions.attachment = content;
908
+ internalOptions.media = content;
897
909
  internalOptions.isViewOnce = options.isViewOnce,
898
910
  content = '';
899
911
  } else if (options.media instanceof MessageMedia) {
900
- internalOptions.attachment = options.media;
912
+ internalOptions.media = options.media;
901
913
  internalOptions.caption = content;
902
914
  internalOptions.isViewOnce = options.isViewOnce,
903
915
  content = '';
@@ -914,17 +926,19 @@ class Client extends EventEmitter {
914
926
  internalOptions.contactCardList = content.map(contact => contact.id._serialized);
915
927
  content = '';
916
928
  } else if (content instanceof Buttons) {
929
+ console.warn('Buttons are now deprecated. See more at https://www.youtube.com/watch?v=hv1R1rLeVVE.');
917
930
  if (content.type !== 'chat') { internalOptions.attachment = content.body; }
918
931
  internalOptions.buttons = content;
919
932
  content = '';
920
933
  } else if (content instanceof List) {
934
+ console.warn('Lists are now deprecated. See more at https://www.youtube.com/watch?v=hv1R1rLeVVE.');
921
935
  internalOptions.list = content;
922
936
  content = '';
923
937
  }
924
938
 
925
- if (internalOptions.sendMediaAsSticker && internalOptions.attachment) {
926
- internalOptions.attachment = await Util.formatToWebpSticker(
927
- internalOptions.attachment, {
939
+ if (internalOptions.sendMediaAsSticker && internalOptions.media) {
940
+ internalOptions.media = await Util.formatToWebpSticker(
941
+ internalOptions.media, {
928
942
  name: options.stickerName,
929
943
  author: options.stickerAuthor,
930
944
  categories: options.stickerCategories
@@ -932,20 +946,60 @@ class Client extends EventEmitter {
932
946
  );
933
947
  }
934
948
 
935
- const newMessage = await this.pupPage.evaluate(async (chatId, message, options, sendSeen) => {
936
- const chatWid = window.Store.WidFactory.createWid(chatId);
937
- const chat = await window.Store.Chat.find(chatWid);
949
+ const sentMsg = await this.pupPage.evaluate(async (chatId, content, options, sendSeen) => {
950
+ const chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
938
951
 
952
+ if (!chat) return null;
939
953
 
940
954
  if (sendSeen) {
941
955
  await window.WWebJS.sendSeen(chatId);
942
956
  }
943
957
 
944
- const msg = await window.WWebJS.sendMessage(chat, message, options, sendSeen);
945
- return window.WWebJS.getMessageModel(msg);
958
+ const msg = await window.WWebJS.sendMessage(chat, content, options);
959
+ return msg
960
+ ? window.WWebJS.getMessageModel(msg)
961
+ : undefined;
946
962
  }, chatId, content, internalOptions, sendSeen);
947
963
 
948
- return new Message(this, newMessage);
964
+ return sentMsg
965
+ ? new Message(this, sentMsg)
966
+ : undefined;
967
+ }
968
+
969
+ /**
970
+ * @typedef {Object} SendChannelAdminInviteOptions
971
+ * @property {?string} comment The comment to be added to an invitation
972
+ */
973
+
974
+ /**
975
+ * Sends a channel admin invitation to a user, allowing them to become an admin of the channel
976
+ * @param {string} chatId The ID of a user to send the channel admin invitation to
977
+ * @param {string} channelId The ID of a channel for which the invitation is being sent
978
+ * @param {SendChannelAdminInviteOptions} options
979
+ * @returns {Promise<boolean>} Returns true if an invitation was sent successfully, false otherwise
980
+ */
981
+ async sendChannelAdminInvite(chatId, channelId, options = {}) {
982
+ const response = await this.pupPage.evaluate(async (chatId, channelId, options) => {
983
+ const channelWid = window.Store.WidFactory.createWid(channelId);
984
+ const chatWid = window.Store.WidFactory.createWid(chatId);
985
+ const chat = window.Store.Chat.get(chatWid) || (await window.Store.Chat.find(chatWid));
986
+
987
+ if (!chatWid.isUser()) {
988
+ return false;
989
+ }
990
+
991
+ return await window.Store.SendChannelMessage.sendNewsletterAdminInviteMessage(
992
+ chat,
993
+ {
994
+ newsletterWid: channelWid,
995
+ invitee: chatWid,
996
+ inviteMessage: options.comment,
997
+ base64Thumb: await window.WWebJS.getProfilePicThumbToBase64(channelWid)
998
+ }
999
+ );
1000
+ }, chatId, channelId, options);
1001
+
1002
+ return response.messageSendResult === 'OK';
949
1003
  }
950
1004
 
951
1005
  /**
@@ -971,7 +1025,7 @@ class Client extends EventEmitter {
971
1025
  * @returns {Promise<Array<Chat>>}
972
1026
  */
973
1027
  async getChats() {
974
- let chats = await this.pupPage.evaluate(async () => {
1028
+ const chats = await this.pupPage.evaluate(async () => {
975
1029
  return await window.WWebJS.getChats();
976
1030
  });
977
1031
 
@@ -979,16 +1033,51 @@ class Client extends EventEmitter {
979
1033
  }
980
1034
 
981
1035
  /**
982
- * Get chat instance by ID
1036
+ * Gets all cached {@link Channel} instance
1037
+ * @returns {Promise<Array<Channel>>}
1038
+ */
1039
+ async getChannels() {
1040
+ const channels = await this.pupPage.evaluate(async () => {
1041
+ return await window.WWebJS.getChannels();
1042
+ });
1043
+
1044
+ return channels.map((channel) => ChatFactory.create(this, channel));
1045
+ }
1046
+
1047
+ /**
1048
+ * Gets chat or channel instance by ID
983
1049
  * @param {string} chatId
984
- * @returns {Promise<Chat>}
1050
+ * @returns {Promise<Chat|Channel>}
985
1051
  */
986
1052
  async getChatById(chatId) {
987
- let chat = await this.pupPage.evaluate(async chatId => {
1053
+ const chat = await this.pupPage.evaluate(async chatId => {
988
1054
  return await window.WWebJS.getChat(chatId);
989
1055
  }, chatId);
1056
+ return chat
1057
+ ? ChatFactory.create(this, chat)
1058
+ : undefined;
1059
+ }
990
1060
 
991
- return ChatFactory.create(this, chat);
1061
+ /**
1062
+ * Gets a {@link Channel} instance by invite code
1063
+ * @param {string} inviteCode The code that comes after the 'https://whatsapp.com/channel/'
1064
+ * @returns {Promise<Channel>}
1065
+ */
1066
+ async getChannelByInviteCode(inviteCode) {
1067
+ const channel = await this.pupPage.evaluate(async (inviteCode) => {
1068
+ let channelMetadata;
1069
+ try {
1070
+ channelMetadata = await window.WWebJS.getChannelMetadata(inviteCode);
1071
+ } catch (err) {
1072
+ if (err.name === 'ServerStatusCodeError') return null;
1073
+ throw err;
1074
+ }
1075
+ return await window.WWebJS.getChat(channelMetadata.id);
1076
+ }, inviteCode);
1077
+
1078
+ return channel
1079
+ ? ChatFactory.create(this, channel)
1080
+ : undefined;
992
1081
  }
993
1082
 
994
1083
  /**
@@ -1058,6 +1147,61 @@ class Client extends EventEmitter {
1058
1147
  return res.gid._serialized;
1059
1148
  }
1060
1149
 
1150
+ /**
1151
+ * Accepts a channel admin invitation and promotes the current user to a channel admin
1152
+ * @param {string} channelId The channel ID to accept the admin invitation from
1153
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
1154
+ */
1155
+ async acceptChannelAdminInvite(channelId) {
1156
+ return await this.pupPage.evaluate(async (channelId) => {
1157
+ try {
1158
+ await window.Store.ChannelUtils.acceptNewsletterAdminInvite(channelId);
1159
+ return true;
1160
+ } catch (err) {
1161
+ if (err.name === 'ServerStatusCodeError') return false;
1162
+ throw err;
1163
+ }
1164
+ }, channelId);
1165
+ }
1166
+
1167
+ /**
1168
+ * Revokes a channel admin invitation sent to a user by a channel owner
1169
+ * @param {string} channelId The channel ID an invitation belongs to
1170
+ * @param {string} userId The user ID the invitation was sent to
1171
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
1172
+ */
1173
+ async revokeChannelAdminInvite(channelId, userId) {
1174
+ return await this.pupPage.evaluate(async (channelId, userId) => {
1175
+ try {
1176
+ const userWid = window.Store.WidFactory.createWid(userId);
1177
+ await window.Store.ChannelUtils.revokeNewsletterAdminInvite(channelId, userWid);
1178
+ return true;
1179
+ } catch (err) {
1180
+ if (err.name === 'ServerStatusCodeError') return false;
1181
+ throw err;
1182
+ }
1183
+ }, channelId, userId);
1184
+ }
1185
+
1186
+ /**
1187
+ * Demotes a channel admin to a regular subscriber (can be used also for self-demotion)
1188
+ * @param {string} channelId The channel ID to demote an admin in
1189
+ * @param {string} userId The user ID to demote
1190
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
1191
+ */
1192
+ async demoteChannelAdmin(channelId, userId) {
1193
+ return await this.pupPage.evaluate(async (channelId, userId) => {
1194
+ try {
1195
+ const userWid = window.Store.WidFactory.createWid(userId);
1196
+ await window.Store.ChannelUtils.demoteNewsletterAdmin(channelId, userWid);
1197
+ return true;
1198
+ } catch (err) {
1199
+ if (err.name === 'ServerStatusCodeError') return false;
1200
+ throw err;
1201
+ }
1202
+ }, channelId, userId);
1203
+ }
1204
+
1061
1205
  /**
1062
1206
  * Accepts a private invitation to join a group
1063
1207
  * @param {object} inviteInfo Invite V4 Info
@@ -1134,7 +1278,7 @@ class Client extends EventEmitter {
1134
1278
  */
1135
1279
  async archiveChat(chatId) {
1136
1280
  return await this.pupPage.evaluate(async chatId => {
1137
- let chat = await window.Store.Chat.get(chatId);
1281
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
1138
1282
  await window.Store.Cmd.archiveChat(chat, true);
1139
1283
  return true;
1140
1284
  }, chatId);
@@ -1146,7 +1290,7 @@ class Client extends EventEmitter {
1146
1290
  */
1147
1291
  async unarchiveChat(chatId) {
1148
1292
  return await this.pupPage.evaluate(async chatId => {
1149
- let chat = await window.Store.Chat.get(chatId);
1293
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
1150
1294
  await window.Store.Cmd.archiveChat(chat, false);
1151
1295
  return false;
1152
1296
  }, chatId);
@@ -1158,7 +1302,7 @@ class Client extends EventEmitter {
1158
1302
  */
1159
1303
  async pinChat(chatId) {
1160
1304
  return this.pupPage.evaluate(async chatId => {
1161
- let chat = window.Store.Chat.get(chatId);
1305
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
1162
1306
  if (chat.pin) {
1163
1307
  return true;
1164
1308
  }
@@ -1181,7 +1325,7 @@ class Client extends EventEmitter {
1181
1325
  */
1182
1326
  async unpinChat(chatId) {
1183
1327
  return this.pupPage.evaluate(async chatId => {
1184
- let chat = window.Store.Chat.get(chatId);
1328
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
1185
1329
  if (!chat.pin) {
1186
1330
  return false;
1187
1331
  }
@@ -1233,7 +1377,7 @@ class Client extends EventEmitter {
1233
1377
  */
1234
1378
  async markChatUnread(chatId) {
1235
1379
  await this.pupPage.evaluate(async chatId => {
1236
- let chat = await window.Store.Chat.get(chatId);
1380
+ let chat = await window.WWebJS.getChat(chatId, { getAsModel: false });
1237
1381
  await window.Store.Cmd.markChatUnread(chat, true);
1238
1382
  }, chatId);
1239
1383
  }
@@ -1435,7 +1579,7 @@ class Client extends EventEmitter {
1435
1579
  for (const participant of createGroupResult.participants) {
1436
1580
  let isInviteV4Sent = false;
1437
1581
  const participantId = participant.wid._serialized;
1438
- const statusCode = participant.error ?? 200;
1582
+ const statusCode = participant.error || 200;
1439
1583
 
1440
1584
  if (autoSendInviteV4 && statusCode === 403) {
1441
1585
  window.Store.Contact.gadd(participant.wid, { silent: true });
@@ -1474,6 +1618,219 @@ class Client extends EventEmitter {
1474
1618
  }, title, participants, options);
1475
1619
  }
1476
1620
 
1621
+ /**
1622
+ * An object that handles the result for {@link createChannel} method
1623
+ * @typedef {Object} CreateChannelResult
1624
+ * @property {string} title A channel title
1625
+ * @property {ChatId} nid An object that handels the newly created channel ID
1626
+ * @property {string} nid.server 'newsletter'
1627
+ * @property {string} nid.user 'XXXXXXXXXX'
1628
+ * @property {string} nid._serialized 'XXXXXXXXXX@newsletter'
1629
+ * @property {string} inviteLink The channel invite link, starts with 'https://whatsapp.com/channel/'
1630
+ * @property {number} createdAtTs The timestamp the channel was created at
1631
+ */
1632
+
1633
+ /**
1634
+ * Options for the channel creation
1635
+ * @typedef {Object} CreateChannelOptions
1636
+ * @property {?string} description The channel description
1637
+ * @property {?MessageMedia} picture The channel profile picture
1638
+ */
1639
+
1640
+ /**
1641
+ * Creates a new channel
1642
+ * @param {string} title The channel name
1643
+ * @param {CreateChannelOptions} options
1644
+ * @returns {Promise<CreateChannelResult|string>} Returns an object that handles the result for the channel creation or an error message as a string
1645
+ */
1646
+ async createChannel(title, options = {}) {
1647
+ return await this.pupPage.evaluate(async (title, options) => {
1648
+ let response, { description = null, picture = null } = options;
1649
+
1650
+ if (!window.Store.ChannelUtils.isNewsletterCreationEnabled()) {
1651
+ return 'CreateChannelError: A channel creation is not enabled';
1652
+ }
1653
+
1654
+ if (picture) {
1655
+ picture = await window.WWebJS.cropAndResizeImage(picture, {
1656
+ asDataUrl: true,
1657
+ mimetype: 'image/jpeg',
1658
+ size: 640,
1659
+ quality: 1
1660
+ });
1661
+ }
1662
+
1663
+ try {
1664
+ response = await window.Store.ChannelUtils.createNewsletterQuery({
1665
+ name: title,
1666
+ description: description,
1667
+ picture: picture,
1668
+ });
1669
+ } catch (err) {
1670
+ if (err.name === 'ServerStatusCodeError') {
1671
+ return 'CreateChannelError: An error occupied while creating a channel';
1672
+ }
1673
+ throw err;
1674
+ }
1675
+
1676
+ return {
1677
+ title: title,
1678
+ nid: window.Store.JidToWid.newsletterJidToWid(response.idJid),
1679
+ inviteLink: `https://whatsapp.com/channel/${response.newsletterInviteLinkMetadataMixin.inviteCode}`,
1680
+ createdAtTs: response.newsletterCreationTimeMetadataMixin.creationTimeValue
1681
+ };
1682
+ }, title, options);
1683
+ }
1684
+
1685
+ /**
1686
+ * Subscribe to channel
1687
+ * @param {string} channelId The channel ID
1688
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
1689
+ */
1690
+ async subscribeToChannel(channelId) {
1691
+ return await this.pupPage.evaluate(async (channelId) => {
1692
+ return await window.WWebJS.subscribeToUnsubscribeFromChannel(channelId, 'Subscribe');
1693
+ }, channelId);
1694
+ }
1695
+
1696
+ /**
1697
+ * Options for unsubscribe from a channel
1698
+ * @typedef {Object} UnsubscribeOptions
1699
+ * @property {boolean} [deleteLocalModels = false] If true, after an unsubscription, it will completely remove a channel from the channel collection making it seem like the current user have never interacted with it. Otherwise it will only remove a channel from the list of channels the current user is subscribed to and will set the membership type for that channel to GUEST
1700
+ */
1701
+
1702
+ /**
1703
+ * Unsubscribe from channel
1704
+ * @param {string} channelId The channel ID
1705
+ * @param {UnsubscribeOptions} options
1706
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
1707
+ */
1708
+ async unsubscribeFromChannel(channelId, options) {
1709
+ return await this.pupPage.evaluate(async (channelId, options) => {
1710
+ return await window.WWebJS.subscribeToUnsubscribeFromChannel(channelId, 'Unsubscribe', options);
1711
+ }, channelId, options);
1712
+ }
1713
+
1714
+ /**
1715
+ * Options for transferring a channel ownership to another user
1716
+ * @typedef {Object} TransferChannelOwnershipOptions
1717
+ * @property {boolean} [shouldDismissSelfAsAdmin = false] If true, after the channel ownership is being transferred to another user, the current user will be dismissed as a channel admin and will become to a channel subscriber.
1718
+ */
1719
+
1720
+ /**
1721
+ * Transfers a channel ownership to another user.
1722
+ * Note: the user you are transferring the channel ownership to must be a channel admin.
1723
+ * @param {string} channelId
1724
+ * @param {string} newOwnerId
1725
+ * @param {TransferChannelOwnershipOptions} options
1726
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
1727
+ */
1728
+ async transferChannelOwnership(channelId, newOwnerId, options = {}) {
1729
+ return await this.pupPage.evaluate(async (channelId, newOwnerId, options) => {
1730
+ const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
1731
+ const newOwner = window.Store.Contact.get(newOwnerId) || (await window.Store.Contact.find(newOwnerId));
1732
+ if (!channel.newsletterMetadata) {
1733
+ await window.Store.NewsletterMetadataCollection.update(channel.id);
1734
+ }
1735
+
1736
+ try {
1737
+ await window.Store.ChannelUtils.changeNewsletterOwnerAction(channel, newOwner);
1738
+
1739
+ if (options.shouldDismissSelfAsAdmin) {
1740
+ const meContact = window.Store.ContactCollection.getMeContact();
1741
+ meContact && (await window.Store.ChannelUtils.demoteNewsletterAdminAction(channel, meContact));
1742
+ }
1743
+ } catch (error) {
1744
+ return false;
1745
+ }
1746
+
1747
+ return true;
1748
+ }, channelId, newOwnerId, options);
1749
+ }
1750
+
1751
+ /**
1752
+ * Searches for channels based on search criteria, there are some notes:
1753
+ * 1. The method finds only channels you are not subscribed to currently
1754
+ * 2. If you have never been subscribed to a found channel
1755
+ * or you have unsubscribed from it with {@link UnsubscribeOptions.deleteLocalModels} set to 'true',
1756
+ * the lastMessage property of a found channel will be 'null'
1757
+ *
1758
+ * @param {Object} searchOptions Search options
1759
+ * @param {string} [searchOptions.searchText = ''] Text to search
1760
+ * @param {Array<string>} [searchOptions.countryCodes = [your local region]] Array of country codes in 'ISO 3166-1 alpha-2' standart (@see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) to search for channels created in these countries
1761
+ * @param {boolean} [searchOptions.skipSubscribedNewsletters = false] If true, channels that user is subscribed to won't appear in found channels
1762
+ * @param {number} [searchOptions.view = 0] View type, makes sense only when the searchText is empty. Valid values to provide are:
1763
+ * 0 for RECOMMENDED channels
1764
+ * 1 for TRENDING channels
1765
+ * 2 for POPULAR channels
1766
+ * 3 for NEW channels
1767
+ * @param {number} [searchOptions.limit = 50] The limit of found channels to be appear in the returnig result
1768
+ * @returns {Promise<Array<Channel>|[]>} Returns an array of Channel objects or an empty array if no channels were found
1769
+ */
1770
+ async searchChannels(searchOptions = {}) {
1771
+ return await this.pupPage.evaluate(async ({
1772
+ searchText = '',
1773
+ countryCodes = [window.Store.ChannelUtils.currentRegion],
1774
+ skipSubscribedNewsletters = false,
1775
+ view = 0,
1776
+ limit = 50
1777
+ }) => {
1778
+ searchText = searchText.trim();
1779
+ const currentRegion = window.Store.ChannelUtils.currentRegion;
1780
+ if (![0, 1, 2, 3].includes(view)) view = 0;
1781
+
1782
+ countryCodes = countryCodes.length === 1 && countryCodes[0] === currentRegion
1783
+ ? countryCodes
1784
+ : countryCodes.filter((code) => Object.keys(window.Store.ChannelUtils.countryCodesIso).includes(code));
1785
+
1786
+ const viewTypeMapping = {
1787
+ 0: 'RECOMMENDED',
1788
+ 1: 'TRENDING',
1789
+ 2: 'POPULAR',
1790
+ 3: 'NEW'
1791
+ };
1792
+
1793
+ searchOptions = {
1794
+ searchText: searchText,
1795
+ countryCodes: countryCodes,
1796
+ skipSubscribedNewsletters: skipSubscribedNewsletters,
1797
+ view: viewTypeMapping[view],
1798
+ categories: [],
1799
+ cursorToken: ''
1800
+ };
1801
+
1802
+ const originalFunction = window.Store.ChannelUtils.getNewsletterDirectoryPageSize;
1803
+ limit !== 50 && (window.Store.ChannelUtils.getNewsletterDirectoryPageSize = () => limit);
1804
+
1805
+ const channels = (await window.Store.ChannelUtils.fetchNewsletterDirectories(searchOptions)).newsletters;
1806
+
1807
+ limit !== 50 && (window.Store.ChannelUtils.getNewsletterDirectoryPageSize = originalFunction);
1808
+
1809
+ return channels
1810
+ ? await Promise.all(channels.map((channel) => window.WWebJS.getChatModel(channel, { isChannel: true })))
1811
+ : [];
1812
+ }, searchOptions);
1813
+ }
1814
+
1815
+ /**
1816
+ * Deletes the channel you created
1817
+ * @param {string} channelId The ID of a channel to delete
1818
+ * @returns {Promise<boolean>} Returns true if the operation completed successfully, false otherwise
1819
+ */
1820
+ async deleteChannel(channelId) {
1821
+ return await this.client.pupPage.evaluate(async (channelId) => {
1822
+ const channel = await window.WWebJS.getChat(channelId, { getAsModel: false });
1823
+ if (!channel) return false;
1824
+ try {
1825
+ await window.Store.ChannelUtils.deleteNewsletterAction(channel);
1826
+ return true;
1827
+ } catch (err) {
1828
+ if (err.name === 'ServerStatusCodeError') return false;
1829
+ throw err;
1830
+ }
1831
+ }, channelId);
1832
+ }
1833
+
1477
1834
  /**
1478
1835
  * Get all current Labels
1479
1836
  * @returns {Promise<Array<Label>>}
@@ -2,15 +2,20 @@
2
2
 
3
3
  const PrivateChat = require('../structures/PrivateChat');
4
4
  const GroupChat = require('../structures/GroupChat');
5
+ const Channel = require('../structures/Channel');
5
6
 
6
7
  class ChatFactory {
7
8
  static create(client, data) {
8
- if(data.isGroup) {
9
+ if (data.isGroup) {
9
10
  return new GroupChat(client, data);
10
11
  }
12
+
13
+ if (data.isChannel) {
14
+ return new Channel(client, data);
15
+ }
11
16
 
12
17
  return new PrivateChat(client, data);
13
18
  }
14
19
  }
15
20
 
16
- module.exports = ChatFactory;
21
+ module.exports = ChatFactory;