whatsapp-web.js 1.22.2-alpha.0 → 1.22.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example.js +152 -1
- package/index.d.ts +163 -36
- package/package.json +1 -1
- package/src/Client.js +186 -30
- package/src/structures/GroupChat.js +180 -16
- package/src/structures/Location.js +32 -4
- package/src/structures/Message.js +15 -1
- package/src/util/Constants.js +1 -0
- package/src/util/Injected.js +255 -16
package/src/Client.js
CHANGED
|
@@ -51,6 +51,7 @@ const NoAuth = require('./authStrategies/NoAuth');
|
|
|
51
51
|
* @fires Client#change_state
|
|
52
52
|
* @fires Client#contact_changed
|
|
53
53
|
* @fires Client#group_admin_changed
|
|
54
|
+
* @fires Client#group_membership_request
|
|
54
55
|
*/
|
|
55
56
|
class Client extends EventEmitter {
|
|
56
57
|
constructor(options = {}) {
|
|
@@ -172,7 +173,7 @@ class Client extends EventEmitter {
|
|
|
172
173
|
}
|
|
173
174
|
);
|
|
174
175
|
|
|
175
|
-
const INTRO_IMG_SELECTOR = '[data-icon=\'
|
|
176
|
+
const INTRO_IMG_SELECTOR = '[data-icon=\'search\']';
|
|
176
177
|
const INTRO_QRCODE_SELECTOR = 'div[data-ref] canvas';
|
|
177
178
|
|
|
178
179
|
// Checks which selector appears first
|
|
@@ -285,13 +286,13 @@ class Client extends EventEmitter {
|
|
|
285
286
|
*/
|
|
286
287
|
window.compareWwebVersions = (lOperand, operator, rOperand) => {
|
|
287
288
|
if (!['>', '>=', '<', '<=', '='].includes(operator)) {
|
|
288
|
-
throw class _ extends Error {
|
|
289
|
+
throw new class _ extends Error {
|
|
289
290
|
constructor(m) { super(m); this.name = 'CompareWwebVersionsError'; }
|
|
290
291
|
}('Invalid comparison operator is provided');
|
|
291
292
|
|
|
292
293
|
}
|
|
293
294
|
if (typeof lOperand !== 'string' || typeof rOperand !== 'string') {
|
|
294
|
-
throw class _ extends Error {
|
|
295
|
+
throw new class _ extends Error {
|
|
295
296
|
constructor(m) { super(m); this.name = 'CompareWwebVersionsError'; }
|
|
296
297
|
}('A non-string WWeb version type is provided');
|
|
297
298
|
}
|
|
@@ -379,6 +380,17 @@ class Client extends EventEmitter {
|
|
|
379
380
|
* @param {GroupNotification} notification GroupNotification with more information about the action
|
|
380
381
|
*/
|
|
381
382
|
this.emit(Events.GROUP_ADMIN_CHANGED, notification);
|
|
383
|
+
} else if (msg.subtype === 'created_membership_requests') {
|
|
384
|
+
/**
|
|
385
|
+
* Emitted when some user requested to join the group
|
|
386
|
+
* that has the membership approval mode turned on
|
|
387
|
+
* @event Client#group_membership_request
|
|
388
|
+
* @param {GroupNotification} notification GroupNotification with more information about the action
|
|
389
|
+
* @param {string} notification.chatId The group ID the request was made for
|
|
390
|
+
* @param {string} notification.author The user ID that made a request
|
|
391
|
+
* @param {number} notification.timestamp The timestamp the request was made at
|
|
392
|
+
*/
|
|
393
|
+
this.emit(Events.GROUP_MEMBERSHIP_REQUEST, notification);
|
|
382
394
|
} else {
|
|
383
395
|
/**
|
|
384
396
|
* Emitted when group settings are updated, such as subject, description or picture.
|
|
@@ -975,7 +987,7 @@ class Client extends EventEmitter {
|
|
|
975
987
|
*/
|
|
976
988
|
async getInviteInfo(inviteCode) {
|
|
977
989
|
return await this.pupPage.evaluate(inviteCode => {
|
|
978
|
-
return window.Store.
|
|
990
|
+
return window.Store.GroupInvite.queryGroupInvite(inviteCode);
|
|
979
991
|
}, inviteCode);
|
|
980
992
|
}
|
|
981
993
|
|
|
@@ -986,7 +998,7 @@ class Client extends EventEmitter {
|
|
|
986
998
|
*/
|
|
987
999
|
async acceptInvite(inviteCode) {
|
|
988
1000
|
const res = await this.pupPage.evaluate(async inviteCode => {
|
|
989
|
-
return await window.Store.
|
|
1001
|
+
return await window.Store.GroupInvite.joinGroupViaInvite(inviteCode);
|
|
990
1002
|
}, inviteCode);
|
|
991
1003
|
|
|
992
1004
|
return res.gid._serialized;
|
|
@@ -1003,7 +1015,7 @@ class Client extends EventEmitter {
|
|
|
1003
1015
|
return this.pupPage.evaluate(async inviteInfo => {
|
|
1004
1016
|
let { groupId, fromId, inviteCode, inviteCodeExp } = inviteInfo;
|
|
1005
1017
|
let userWid = window.Store.WidFactory.createWid(fromId);
|
|
1006
|
-
return await window.Store.
|
|
1018
|
+
return await window.Store.GroupInviteV4.joinGroupViaInviteV4(inviteCode, String(inviteCodeExp), groupId, userWid);
|
|
1007
1019
|
}, inviteInfo);
|
|
1008
1020
|
}
|
|
1009
1021
|
|
|
@@ -1279,35 +1291,116 @@ class Client extends EventEmitter {
|
|
|
1279
1291
|
}
|
|
1280
1292
|
|
|
1281
1293
|
/**
|
|
1282
|
-
*
|
|
1283
|
-
* @
|
|
1284
|
-
* @
|
|
1285
|
-
* @
|
|
1286
|
-
* @
|
|
1287
|
-
* @
|
|
1294
|
+
* An object that represents the result for a participant added to a group
|
|
1295
|
+
* @typedef {Object} ParticipantResult
|
|
1296
|
+
* @property {number} statusCode The status code of the result
|
|
1297
|
+
* @property {string} message The result message
|
|
1298
|
+
* @property {boolean} isGroupCreator Indicates if the participant is a group creator
|
|
1299
|
+
* @property {boolean} isInviteV4Sent Indicates if the inviteV4 was sent to the participant
|
|
1288
1300
|
*/
|
|
1289
|
-
async createGroup(name, participants) {
|
|
1290
|
-
if (!Array.isArray(participants) || participants.length == 0) {
|
|
1291
|
-
throw 'You need to add at least one other participant to the group';
|
|
1292
|
-
}
|
|
1293
1301
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1302
|
+
/**
|
|
1303
|
+
* An object that handles the result for {@link createGroup} method
|
|
1304
|
+
* @typedef {Object} CreateGroupResult
|
|
1305
|
+
* @property {string} title A group title
|
|
1306
|
+
* @property {Object} gid An object that handles the newly created group ID
|
|
1307
|
+
* @property {string} gid.server
|
|
1308
|
+
* @property {string} gid.user
|
|
1309
|
+
* @property {string} gid._serialized
|
|
1310
|
+
* @property {Object.<string, ParticipantResult>} participants An object that handles the result value for each added to the group participant
|
|
1311
|
+
*/
|
|
1312
|
+
|
|
1313
|
+
/**
|
|
1314
|
+
* An object that handles options for group creation
|
|
1315
|
+
* @typedef {Object} CreateGroupOptions
|
|
1316
|
+
* @property {number} [messageTimer = 0] The number of seconds for the messages to disappear in the group (0 by default, won't take an effect if the group is been creating with myself only)
|
|
1317
|
+
* @property {string|undefined} parentGroupId The ID of a parent community group to link the newly created group with (won't take an effect if the group is been creating with myself only)
|
|
1318
|
+
* @property {boolean} [autoSendInviteV4 = true] If true, the inviteV4 will be sent to those participants who have restricted others from being automatically added to groups, otherwise the inviteV4 won't be sent (true by default)
|
|
1319
|
+
* @property {string} [comment = ''] The comment to be added to an inviteV4 (empty string by default)
|
|
1320
|
+
*/
|
|
1321
|
+
|
|
1322
|
+
/**
|
|
1323
|
+
* Creates a new group
|
|
1324
|
+
* @param {string} title Group title
|
|
1325
|
+
* @param {string|Contact|Array<Contact|string>|undefined} participants A single Contact object or an ID as a string or an array of Contact objects or contact IDs to add to the group
|
|
1326
|
+
* @param {CreateGroupOptions} options An object that handles options for group creation
|
|
1327
|
+
* @returns {Promise<CreateGroupResult|string>} Object with resulting data or an error message as a string
|
|
1328
|
+
*/
|
|
1329
|
+
async createGroup(title, participants = [], options = {}) {
|
|
1330
|
+
!Array.isArray(participants) && (participants = [participants]);
|
|
1331
|
+
participants.map(p => (p instanceof Contact) ? p.id._serialized : p);
|
|
1332
|
+
|
|
1333
|
+
return await this.pupPage.evaluate(async (title, participants, options) => {
|
|
1334
|
+
const { messageTimer = 0, parentGroupId, autoSendInviteV4 = true, comment = '' } = options;
|
|
1335
|
+
const participantData = {}, participantWids = [], failedParticipants = [];
|
|
1336
|
+
let createGroupResult, parentGroupWid;
|
|
1337
|
+
|
|
1338
|
+
const addParticipantResultCodes = {
|
|
1339
|
+
default: 'An unknown error occupied while adding a participant',
|
|
1340
|
+
200: 'The participant was added successfully',
|
|
1341
|
+
403: 'The participant can be added by sending private invitation only',
|
|
1342
|
+
404: 'The phone number is not registered on WhatsApp'
|
|
1343
|
+
};
|
|
1344
|
+
|
|
1345
|
+
for (const participant of participants) {
|
|
1346
|
+
const pWid = window.Store.WidFactory.createWid(participant);
|
|
1347
|
+
if ((await window.Store.QueryExist(pWid))?.wid) participantWids.push(pWid);
|
|
1348
|
+
else failedParticipants.push(participant);
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
parentGroupId && (parentGroupWid = window.Store.WidFactory.createWid(parentGroupId));
|
|
1352
|
+
|
|
1353
|
+
try {
|
|
1354
|
+
createGroupResult = await window.Store.GroupUtils.createGroup(
|
|
1355
|
+
title,
|
|
1356
|
+
participantWids,
|
|
1357
|
+
messageTimer,
|
|
1358
|
+
parentGroupWid
|
|
1359
|
+
);
|
|
1360
|
+
} catch (err) {
|
|
1361
|
+
return 'CreateGroupError: An unknown error occupied while creating a group';
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
for (const participant of createGroupResult.participants) {
|
|
1365
|
+
let isInviteV4Sent = false;
|
|
1366
|
+
const participantId = participant.wid._serialized;
|
|
1367
|
+
const statusCode = participant.error ?? 200;
|
|
1368
|
+
|
|
1369
|
+
if (autoSendInviteV4 && statusCode === 403) {
|
|
1370
|
+
window.Store.ContactCollection.gadd(participant.wid, { silent: true });
|
|
1371
|
+
const addParticipantResult = await window.Store.GroupInviteV4.sendGroupInviteMessage(
|
|
1372
|
+
await window.Store.Chat.find(participant.wid),
|
|
1373
|
+
createGroupResult.wid._serialized,
|
|
1374
|
+
createGroupResult.subject,
|
|
1375
|
+
participant.invite_code,
|
|
1376
|
+
participant.invite_code_exp,
|
|
1377
|
+
comment,
|
|
1378
|
+
await window.WWebJS.getProfilePicThumbToBase64(createGroupResult.wid)
|
|
1379
|
+
);
|
|
1380
|
+
isInviteV4Sent = window.compareWwebVersions(window.Debug.VERSION, '<', '2.2335.6')
|
|
1381
|
+
? addParticipantResult === 'OK'
|
|
1382
|
+
: addParticipantResult.messageSendResult === 'OK';
|
|
1383
|
+
}
|
|
1297
1384
|
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1385
|
+
participantData[participantId] = {
|
|
1386
|
+
statusCode: statusCode,
|
|
1387
|
+
message: addParticipantResultCodes[statusCode] || addParticipantResultCodes.default,
|
|
1388
|
+
isGroupCreator: participant.type === 'superadmin',
|
|
1389
|
+
isInviteV4Sent: isInviteV4Sent
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1302
1392
|
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1393
|
+
for (const f of failedParticipants) {
|
|
1394
|
+
participantData[f] = {
|
|
1395
|
+
statusCode: 404,
|
|
1396
|
+
message: addParticipantResultCodes[404],
|
|
1397
|
+
isGroupCreator: false,
|
|
1398
|
+
isInviteV4Sent: false
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1309
1401
|
|
|
1310
|
-
|
|
1402
|
+
return { title: title, gid: createGroupResult.wid, participants: participantData };
|
|
1403
|
+
}, title, participants, options);
|
|
1311
1404
|
}
|
|
1312
1405
|
|
|
1313
1406
|
/**
|
|
@@ -1434,6 +1527,69 @@ class Client extends EventEmitter {
|
|
|
1434
1527
|
return await window.Store.Label.addOrRemoveLabels(actions, chats);
|
|
1435
1528
|
}, labelIds, chatIds);
|
|
1436
1529
|
}
|
|
1530
|
+
|
|
1531
|
+
/**
|
|
1532
|
+
* An object that handles the information about the group membership request
|
|
1533
|
+
* @typedef {Object} GroupMembershipRequest
|
|
1534
|
+
* @property {Object} id The wid of a user who requests to enter the group
|
|
1535
|
+
* @property {Object} addedBy The wid of a user who created that request
|
|
1536
|
+
* @property {Object|null} parentGroupId The wid of a community parent group to which the current group is linked
|
|
1537
|
+
* @property {string} requestMethod The method used to create the request: NonAdminAdd/InviteLink/LinkedGroupJoin
|
|
1538
|
+
* @property {number} t The timestamp the request was created at
|
|
1539
|
+
*/
|
|
1540
|
+
|
|
1541
|
+
/**
|
|
1542
|
+
* Gets an array of membership requests
|
|
1543
|
+
* @param {string} groupId The ID of a group to get membership requests for
|
|
1544
|
+
* @returns {Promise<Array<GroupMembershipRequest>>} An array of membership requests
|
|
1545
|
+
*/
|
|
1546
|
+
async getGroupMembershipRequests(groupId) {
|
|
1547
|
+
return await this.pupPage.evaluate(async (gropId) => {
|
|
1548
|
+
const groupWid = window.Store.WidFactory.createWid(gropId);
|
|
1549
|
+
return await window.Store.MembershipRequestUtils.getMembershipApprovalRequests(groupWid);
|
|
1550
|
+
}, groupId);
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/**
|
|
1554
|
+
* An object that handles the result for membership request action
|
|
1555
|
+
* @typedef {Object} MembershipRequestActionResult
|
|
1556
|
+
* @property {string} requesterId User ID whos membership request was approved/rejected
|
|
1557
|
+
* @property {number|undefined} error An error code that occurred during the operation for the participant
|
|
1558
|
+
* @property {string} message A message with a result of membership request action
|
|
1559
|
+
*/
|
|
1560
|
+
|
|
1561
|
+
/**
|
|
1562
|
+
* An object that handles options for {@link approveGroupMembershipRequests} and {@link rejectGroupMembershipRequests} methods
|
|
1563
|
+
* @typedef {Object} MembershipRequestActionOptions
|
|
1564
|
+
* @property {Array<string>|string|null} requesterIds User ID/s who requested to join the group, if no value is provided, the method will search for all membership requests for that group
|
|
1565
|
+
* @property {Array<number>|number|null} sleep The number of milliseconds to wait before performing an operation for the next requester. If it is an array, a random sleep time between the sleep[0] and sleep[1] values will be added (the difference must be >=100 ms, otherwise, a random sleep time between sleep[1] and sleep[1] + 100 will be added). If sleep is a number, a sleep time equal to its value will be added. By default, sleep is an array with a value of [250, 500]
|
|
1566
|
+
*/
|
|
1567
|
+
|
|
1568
|
+
/**
|
|
1569
|
+
* Approves membership requests if any
|
|
1570
|
+
* @param {string} groupId The group ID to get the membership request for
|
|
1571
|
+
* @param {MembershipRequestActionOptions} options Options for performing a membership request action
|
|
1572
|
+
* @returns {Promise<Array<MembershipRequestActionResult>>} Returns an array of requester IDs whose membership requests were approved and an error for each requester, if any occurred during the operation. If there are no requests, an empty array will be returned
|
|
1573
|
+
*/
|
|
1574
|
+
async approveGroupMembershipRequests(groupId, options = {}) {
|
|
1575
|
+
return await this.pupPage.evaluate(async (groupId, options) => {
|
|
1576
|
+
const { requesterIds = null, sleep = [250, 500] } = options;
|
|
1577
|
+
return await window.WWebJS.membershipRequestAction(groupId, 'Approve', requesterIds, sleep);
|
|
1578
|
+
}, groupId, options);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
/**
|
|
1582
|
+
* Rejects membership requests if any
|
|
1583
|
+
* @param {string} groupId The group ID to get the membership request for
|
|
1584
|
+
* @param {MembershipRequestActionOptions} options Options for performing a membership request action
|
|
1585
|
+
* @returns {Promise<Array<MembershipRequestActionResult>>} Returns an array of requester IDs whose membership requests were rejected and an error for each requester, if any occurred during the operation. If there are no requests, an empty array will be returned
|
|
1586
|
+
*/
|
|
1587
|
+
async rejectGroupMembershipRequests(groupId, options = {}) {
|
|
1588
|
+
return await this.pupPage.evaluate(async (groupId, options) => {
|
|
1589
|
+
const { requesterIds = null, sleep = [250, 500] } = options;
|
|
1590
|
+
return await window.WWebJS.membershipRequestAction(groupId, 'Reject', requesterIds, sleep);
|
|
1591
|
+
}, groupId, options);
|
|
1592
|
+
}
|
|
1437
1593
|
}
|
|
1438
1594
|
|
|
1439
1595
|
module.exports = Client;
|
|
@@ -53,28 +53,141 @@ class GroupChat extends Chat {
|
|
|
53
53
|
return this.groupMetadata.participants;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* An object that handles the result for {@link addParticipants} method
|
|
58
|
+
* @typedef {Object} AddParticipantsResult
|
|
59
|
+
* @property {number} code The code of the result
|
|
60
|
+
* @property {string} message The result message
|
|
61
|
+
* @property {boolean} isInviteV4Sent Indicates if the inviteV4 was sent to the partitipant
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* An object that handles options for adding participants
|
|
66
|
+
* @typedef {Object} AddParticipnatsOptions
|
|
67
|
+
* @property {Array<number>|number} [sleep = [250, 500]] The number of milliseconds to wait before adding the next participant. If it is an array, a random sleep time between the sleep[0] and sleep[1] values will be added (the difference must be >=100 ms, otherwise, a random sleep time between sleep[1] and sleep[1] + 100 will be added). If sleep is a number, a sleep time equal to its value will be added. By default, sleep is an array with a value of [250, 500]
|
|
68
|
+
* @property {boolean} [autoSendInviteV4 = true] If true, the inviteV4 will be sent to those participants who have restricted others from being automatically added to groups, otherwise the inviteV4 won't be sent (true by default)
|
|
69
|
+
* @property {string} [comment = ''] The comment to be added to an inviteV4 (empty string by default)
|
|
70
|
+
*/
|
|
71
|
+
|
|
56
72
|
/**
|
|
57
73
|
* Adds a list of participants by ID to the group
|
|
58
|
-
* @param {Array<string>} participantIds
|
|
59
|
-
* @
|
|
74
|
+
* @param {string|Array<string>} participantIds
|
|
75
|
+
* @param {AddParticipnatsOptions} options An object thay handles options for adding participants
|
|
76
|
+
* @returns {Promise<Object.<string, AddParticipantsResult>|string>} Returns an object with the resulting data or an error message as a string
|
|
60
77
|
*/
|
|
61
|
-
async addParticipants(participantIds) {
|
|
62
|
-
return await this.client.pupPage.evaluate(async (
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
async addParticipants(participantIds, options = {}) {
|
|
79
|
+
return await this.client.pupPage.evaluate(async (groupId, participantIds, options) => {
|
|
80
|
+
const { sleep = [250, 500], autoSendInviteV4 = true, comment = '' } = options;
|
|
81
|
+
const participantData = {};
|
|
82
|
+
|
|
83
|
+
!Array.isArray(participantIds) && (participantIds = [participantIds]);
|
|
84
|
+
const groupWid = window.Store.WidFactory.createWid(groupId);
|
|
85
|
+
const group = await window.Store.Chat.find(groupWid);
|
|
86
|
+
const participantWids = participantIds.map((p) => window.Store.WidFactory.createWid(p));
|
|
87
|
+
|
|
88
|
+
const errorCodes = {
|
|
89
|
+
default: 'An unknown error occupied while adding a participant',
|
|
90
|
+
isGroupEmpty: 'AddParticipantsError: The participant can\'t be added to an empty group',
|
|
91
|
+
iAmNotAdmin: 'AddParticipantsError: You have no admin rights to add a participant to a group',
|
|
92
|
+
200: 'The participant was added successfully',
|
|
93
|
+
403: 'The participant can be added by sending private invitation only',
|
|
94
|
+
404: 'The phone number is not registered on WhatsApp',
|
|
95
|
+
408: 'You cannot add this participant because they recently left the group',
|
|
96
|
+
409: 'The participant is already a group member',
|
|
97
|
+
417: 'The participant can\'t be added to the community. You can invite them privately to join this group through its invite link',
|
|
98
|
+
419: 'The participant can\'t be added because the group is full'
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
await window.Store.GroupMetadata.queryAndUpdate(groupWid);
|
|
102
|
+
const groupMetadata = group.groupMetadata;
|
|
103
|
+
const groupParticipants = groupMetadata?.participants;
|
|
104
|
+
|
|
105
|
+
if (!groupParticipants) {
|
|
106
|
+
return errorCodes.isGroupEmpty;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!group.iAmAdmin()) {
|
|
110
|
+
return errorCodes.iAmNotAdmin;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const _getSleepTime = (sleep) => {
|
|
114
|
+
if (!Array.isArray(sleep) || sleep.length === 2 && sleep[0] === sleep[1]) {
|
|
115
|
+
return sleep;
|
|
116
|
+
}
|
|
117
|
+
if (sleep.length === 1) {
|
|
118
|
+
return sleep[0];
|
|
119
|
+
}
|
|
120
|
+
(sleep[1] - sleep[0]) < 100 && (sleep[0] = sleep[1]) && (sleep[1] += 100);
|
|
121
|
+
return Math.floor(Math.random() * (sleep[1] - sleep[0] + 1)) + sleep[0];
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
for (const pWid of participantWids) {
|
|
125
|
+
const pId = pWid._serialized;
|
|
126
|
+
|
|
127
|
+
participantData[pId] = {
|
|
128
|
+
code: undefined,
|
|
129
|
+
message: undefined,
|
|
130
|
+
isInviteV4Sent: false
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
if (groupParticipants.some(p => p.id._serialized === pId)) {
|
|
134
|
+
participantData[pId].code = 409;
|
|
135
|
+
participantData[pId].message = errorCodes[409];
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!(await window.Store.QueryExist(pWid))?.wid) {
|
|
140
|
+
participantData[pId].code = 404;
|
|
141
|
+
participantData[pId].message = errorCodes[404];
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const rpcResult =
|
|
146
|
+
await window.WWebJS.getAddParticipantsRpcResult(groupMetadata, groupWid, pWid);
|
|
147
|
+
const { code: rpcResultCode } = rpcResult;
|
|
148
|
+
|
|
149
|
+
participantData[pId].code = rpcResultCode;
|
|
150
|
+
participantData[pId].message =
|
|
151
|
+
errorCodes[rpcResultCode] || errorCodes.default;
|
|
152
|
+
|
|
153
|
+
if (autoSendInviteV4 && rpcResultCode === 403) {
|
|
154
|
+
let userChat, isInviteV4Sent = false;
|
|
155
|
+
window.Store.ContactCollection.gadd(pWid, { silent: true });
|
|
156
|
+
|
|
157
|
+
if (rpcResult.name === 'ParticipantRequestCodeCanBeSent' &&
|
|
158
|
+
(userChat = await window.Store.Chat.find(pWid))) {
|
|
159
|
+
const groupName = group.formattedTitle || group.name;
|
|
160
|
+
const res = await window.Store.GroupInviteV4.sendGroupInviteMessage(
|
|
161
|
+
userChat,
|
|
162
|
+
group.id._serialized,
|
|
163
|
+
groupName,
|
|
164
|
+
rpcResult.inviteV4Code,
|
|
165
|
+
rpcResult.inviteV4CodeExp,
|
|
166
|
+
comment,
|
|
167
|
+
await window.WWebJS.getProfilePicThumbToBase64(groupWid)
|
|
168
|
+
);
|
|
169
|
+
isInviteV4Sent = window.compareWwebVersions(window.Debug.VERSION, '<', '2.2335.6')
|
|
170
|
+
? res === 'OK'
|
|
171
|
+
: res.messageSendResult === 'OK';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
participantData[pId].isInviteV4Sent = isInviteV4Sent;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
sleep &&
|
|
178
|
+
participantWids.length > 1 &&
|
|
179
|
+
participantWids.indexOf(pWid) !== participantWids.length - 1 &&
|
|
180
|
+
(await new Promise((resolve) => setTimeout(resolve, _getSleepTime(sleep))));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return participantData;
|
|
184
|
+
}, this.id._serialized, participantIds, options);
|
|
72
185
|
}
|
|
73
186
|
|
|
74
187
|
/**
|
|
75
188
|
* Removes a list of participants by ID to the group
|
|
76
189
|
* @param {Array<string>} participantIds
|
|
77
|
-
* @returns {Promise<
|
|
190
|
+
* @returns {Promise<{ status: number }>}
|
|
78
191
|
*/
|
|
79
192
|
async removeParticipants(participantIds) {
|
|
80
193
|
return await this.client.pupPage.evaluate(async (chatId, participantIds) => {
|
|
@@ -246,7 +359,7 @@ class GroupChat extends Chat {
|
|
|
246
359
|
async getInviteCode() {
|
|
247
360
|
const codeRes = await this.client.pupPage.evaluate(async chatId => {
|
|
248
361
|
const chatWid = window.Store.WidFactory.createWid(chatId);
|
|
249
|
-
return window.Store.
|
|
362
|
+
return window.Store.GroupInvite.queryGroupInviteCode(chatWid);
|
|
250
363
|
}, this.id._serialized);
|
|
251
364
|
|
|
252
365
|
return codeRes.code;
|
|
@@ -259,11 +372,62 @@ class GroupChat extends Chat {
|
|
|
259
372
|
async revokeInvite() {
|
|
260
373
|
const codeRes = await this.client.pupPage.evaluate(chatId => {
|
|
261
374
|
const chatWid = window.Store.WidFactory.createWid(chatId);
|
|
262
|
-
return window.Store.
|
|
375
|
+
return window.Store.GroupInvite.resetGroupInviteCode(chatWid);
|
|
263
376
|
}, this.id._serialized);
|
|
264
377
|
|
|
265
378
|
return codeRes.code;
|
|
266
379
|
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* An object that handles the information about the group membership request
|
|
383
|
+
* @typedef {Object} GroupMembershipRequest
|
|
384
|
+
* @property {Object} id The wid of a user who requests to enter the group
|
|
385
|
+
* @property {Object} addedBy The wid of a user who created that request
|
|
386
|
+
* @property {Object|null} parentGroupId The wid of a community parent group to which the current group is linked
|
|
387
|
+
* @property {string} requestMethod The method used to create the request: NonAdminAdd/InviteLink/LinkedGroupJoin
|
|
388
|
+
* @property {number} t The timestamp the request was created at
|
|
389
|
+
*/
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Gets an array of membership requests
|
|
393
|
+
* @returns {Promise<Array<GroupMembershipRequest>>} An array of membership requests
|
|
394
|
+
*/
|
|
395
|
+
async getGroupMembershipRequests() {
|
|
396
|
+
return await this.client.getGroupMembershipRequests(this.id._serialized);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* An object that handles the result for membership request action
|
|
401
|
+
* @typedef {Object} MembershipRequestActionResult
|
|
402
|
+
* @property {string} requesterId User ID whos membership request was approved/rejected
|
|
403
|
+
* @property {number} error An error code that occurred during the operation for the participant
|
|
404
|
+
* @property {string} message A message with a result of membership request action
|
|
405
|
+
*/
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* An object that handles options for {@link approveGroupMembershipRequests} and {@link rejectGroupMembershipRequests} methods
|
|
409
|
+
* @typedef {Object} MembershipRequestActionOptions
|
|
410
|
+
* @property {Array<string>|string|null} requesterIds User ID/s who requested to join the group, if no value is provided, the method will search for all membership requests for that group
|
|
411
|
+
* @property {Array<number>|number|null} sleep The number of milliseconds to wait before performing an operation for the next requester. If it is an array, a random sleep time between the sleep[0] and sleep[1] values will be added (the difference must be >=100 ms, otherwise, a random sleep time between sleep[1] and sleep[1] + 100 will be added). If sleep is a number, a sleep time equal to its value will be added. By default, sleep is an array with a value of [250, 500]
|
|
412
|
+
*/
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Approves membership requests if any
|
|
416
|
+
* @param {MembershipRequestActionOptions} options Options for performing a membership request action
|
|
417
|
+
* @returns {Promise<Array<MembershipRequestActionResult>>} Returns an array of requester IDs whose membership requests were approved and an error for each requester, if any occurred during the operation. If there are no requests, an empty array will be returned
|
|
418
|
+
*/
|
|
419
|
+
async approveGroupMembershipRequests(options = {}) {
|
|
420
|
+
return await this.client.approveGroupMembershipRequests(this.id._serialized, options);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Rejects membership requests if any
|
|
425
|
+
* @param {MembershipRequestActionOptions} options Options for performing a membership request action
|
|
426
|
+
* @returns {Promise<Array<MembershipRequestActionResult>>} Returns an array of requester IDs whose membership requests were rejected and an error for each requester, if any occurred during the operation. If there are no requests, an empty array will be returned
|
|
427
|
+
*/
|
|
428
|
+
async rejectGroupMembershipRequests(options = {}) {
|
|
429
|
+
return await this.client.rejectGroupMembershipRequests(this.id._serialized, options);
|
|
430
|
+
}
|
|
267
431
|
|
|
268
432
|
/**
|
|
269
433
|
* Makes the bot leave the group
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Location send options
|
|
5
|
+
* @typedef {Object} LocationSendOptions
|
|
6
|
+
* @property {string} [name] Location name
|
|
7
|
+
* @property {string} [address] Location address
|
|
8
|
+
* @property {string} [url] URL address to be shown within a location message
|
|
9
|
+
*/
|
|
10
|
+
|
|
3
11
|
/**
|
|
4
12
|
* Location information
|
|
5
13
|
*/
|
|
@@ -7,9 +15,9 @@ class Location {
|
|
|
7
15
|
/**
|
|
8
16
|
* @param {number} latitude
|
|
9
17
|
* @param {number} longitude
|
|
10
|
-
* @param {
|
|
18
|
+
* @param {LocationSendOptions} [options] Location send options
|
|
11
19
|
*/
|
|
12
|
-
constructor(latitude, longitude,
|
|
20
|
+
constructor(latitude, longitude, options = {}) {
|
|
13
21
|
/**
|
|
14
22
|
* Location latitude
|
|
15
23
|
* @type {number}
|
|
@@ -24,9 +32,29 @@ class Location {
|
|
|
24
32
|
|
|
25
33
|
/**
|
|
26
34
|
* Name for the location
|
|
27
|
-
* @type {
|
|
35
|
+
* @type {string|undefined}
|
|
36
|
+
*/
|
|
37
|
+
this.name = options.name;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Location address
|
|
41
|
+
* @type {string|undefined}
|
|
42
|
+
*/
|
|
43
|
+
this.address = options.address;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* URL address to be shown within a location message
|
|
47
|
+
* @type {string|undefined}
|
|
48
|
+
*/
|
|
49
|
+
this.url = options.url;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Location full description
|
|
53
|
+
* @type {string|undefined}
|
|
28
54
|
*/
|
|
29
|
-
this.description =
|
|
55
|
+
this.description = this.name && this.address
|
|
56
|
+
? `${this.name}\n${this.address}`
|
|
57
|
+
: this.name || this.address || '';
|
|
30
58
|
}
|
|
31
59
|
}
|
|
32
60
|
|
|
@@ -151,7 +151,21 @@ class Message extends Base {
|
|
|
151
151
|
* Location information contained in the message, if the message is type "location"
|
|
152
152
|
* @type {Location}
|
|
153
153
|
*/
|
|
154
|
-
this.location =
|
|
154
|
+
this.location = (() => {
|
|
155
|
+
if (data.type !== MessageTypes.LOCATION) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
let description;
|
|
159
|
+
if (data.loc && typeof data.loc === 'string') {
|
|
160
|
+
let splitted = data.loc.split('\n');
|
|
161
|
+
description = {
|
|
162
|
+
name: splitted[0],
|
|
163
|
+
address: splitted[1],
|
|
164
|
+
url: data.clientUrl
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return new Location(data.lat, data.lng, description);
|
|
168
|
+
})();
|
|
155
169
|
|
|
156
170
|
/**
|
|
157
171
|
* List of vCards contained in the message.
|
package/src/util/Constants.js
CHANGED
|
@@ -56,6 +56,7 @@ exports.Events = {
|
|
|
56
56
|
GROUP_JOIN: 'group_join',
|
|
57
57
|
GROUP_LEAVE: 'group_leave',
|
|
58
58
|
GROUP_ADMIN_CHANGED: 'group_admin_changed',
|
|
59
|
+
GROUP_MEMBERSHIP_REQUEST: 'group_membership_request',
|
|
59
60
|
GROUP_UPDATE: 'group_update',
|
|
60
61
|
QR_RECEIVED: 'qr',
|
|
61
62
|
LOADING_SCREEN: 'loading_screen',
|