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