fix: Client.createGroup + GroupChat.addParticipants (#3670)

* Adjustment addParticipants

* createGroup fully refactored, fixed bugs, added creation options and updated docs

* fix: eslint fix

* refactor: GroupChat.addParticipants fully refactored

* fix: eslint fix

---------

Co-authored-by: alechkos <93551621+alechkos@users.noreply.github.com>
This commit is contained in:
BenyFilho 2025-08-01 00:43:45 -03:00 • committed by GitHub
commit 81fd090e36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 58 additions and 49 deletions

16
index.d.ts vendored
View file

@ -684,6 +684,22 @@ declare namespace WAWebJS {
* @default '' * @default ''
*/ */
comment?: string comment?: string
/** If true, only admins can add members to the group (false by default)
* @default false
*/
memberAddMode?: boolean,
/** If true, group admins will be required to approve anyone who wishes to join the group (false by default)
* @default false
*/
membershipApprovalMode?: boolean,
/** If true, only admins can change group group info (true by default)
* @default true
*/
isRestrict?: boolean,
/** If true, only admins can send messages (false by default)
* @default false
*/
isAnnounce?: boolean,
} }
/** An object that handles the result for createGroup method */ /** An object that handles the result for createGroup method */

View file

@ -1528,6 +1528,10 @@ class Client extends EventEmitter {
* @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) * @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)
* @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) * @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)
* @property {string} [comment = ''] The comment to be added to an inviteV4 (empty string by default) * @property {string} [comment = ''] The comment to be added to an inviteV4 (empty string by default)
* @property {boolean} [memberAddMode = false] If true, only admins can add members to the group (false by default)
* @property {boolean} [membershipApprovalMode = false] If true, group admins will be required to approve anyone who wishes to join the group (false by default)
* @property {boolean} [isRestrict = true] If true, only admins can change group group info (true by default)
* @property {boolean} [isAnnounce = false] If true, only admins can send messages (false by default)
*/ */
/** /**
@ -1542,7 +1546,12 @@ class Client extends EventEmitter {
participants.map(p => (p instanceof Contact) ? p.id._serialized : p); participants.map(p => (p instanceof Contact) ? p.id._serialized : p);
return await this.pupPage.evaluate(async (title, participants, options) => { return await this.pupPage.evaluate(async (title, participants, options) => {
const { messageTimer = 0, parentGroupId, autoSendInviteV4 = true, comment = '' } = options; const {
messageTimer = 0,
parentGroupId,
autoSendInviteV4 = true,
comment = '',
} = options;
const participantData = {}, participantWids = [], failedParticipants = []; const participantData = {}, participantWids = [], failedParticipants = [];
let createGroupResult, parentGroupWid; let createGroupResult, parentGroupWid;
@ -1555,7 +1564,9 @@ class Client extends EventEmitter {
for (const participant of participants) { for (const participant of participants) {
const pWid = window.Store.WidFactory.createWid(participant); const pWid = window.Store.WidFactory.createWid(participant);
if ((await window.Store.QueryExist(pWid))?.wid) participantWids.push(pWid); if ((await window.Store.QueryExist(pWid))?.wid) {
participantWids.push({ phoneNumber: pWid });
}
else failedParticipants.push(participant); else failedParticipants.push(participant);
} }
@ -1564,14 +1575,13 @@ class Client extends EventEmitter {
try { try {
createGroupResult = await window.Store.GroupUtils.createGroup( createGroupResult = await window.Store.GroupUtils.createGroup(
{ {
'memberAddMode': options.memberAddMode === undefined ? true : options.memberAddMode, 'addressingModeOverride': 'lid',
'membershipApprovalMode': options.membershipApprovalMode === undefined ? false : options.membershipApprovalMode, 'memberAddMode': options.memberAddMode ?? false,
'announce': options.announce === undefined ? true : options.announce, 'membershipApprovalMode': options.membershipApprovalMode ?? false,
'announce': options.announce ?? false,
'restrict': options.isRestrict !== undefined ? !options.isRestrict : false,
'ephemeralDuration': messageTimer, 'ephemeralDuration': messageTimer,
'full': undefined,
'parentGroupId': parentGroupWid, 'parentGroupId': parentGroupWid,
'restrict': options.restrict === undefined ? true : options.restrict,
'thumb': undefined,
'title': title, 'title': title,
}, },
participantWids participantWids
@ -1582,13 +1592,14 @@ class Client extends EventEmitter {
for (const participant of createGroupResult.participants) { for (const participant of createGroupResult.participants) {
let isInviteV4Sent = false; let isInviteV4Sent = false;
participant.wid.server == 'lid' && (participant.wid = window.Store.LidUtils.getPhoneNumber(participant.wid));
const participantId = participant.wid._serialized; const participantId = participant.wid._serialized;
const statusCode = participant.error || 200; const statusCode = participant.error || 200;
if (autoSendInviteV4 && statusCode === 403) { if (autoSendInviteV4 && statusCode === 403) {
window.Store.Contact.gadd(participant.wid, { silent: true }); window.Store.Contact.gadd(participant.wid, { silent: true });
const addParticipantResult = await window.Store.GroupInviteV4.sendGroupInviteMessage( const addParticipantResult = await window.Store.GroupInviteV4.sendGroupInviteMessage(
await window.Store.Chat.find(participant.wid), window.Store.Chat.get(participant.wid) || await window.Store.Chat.find(participant.wid),
createGroupResult.wid._serialized, createGroupResult.wid._serialized,
createGroupResult.subject, createGroupResult.subject,
participant.invite_code, participant.invite_code,
@ -1596,9 +1607,7 @@ class Client extends EventEmitter {
comment, comment,
await window.WWebJS.getProfilePicThumbToBase64(createGroupResult.wid) await window.WWebJS.getProfilePicThumbToBase64(createGroupResult.wid)
); );
isInviteV4Sent = window.compareWwebVersions(window.Debug.VERSION, '<', '2.2335.6') isInviteV4Sent = addParticipantResult.messageSendResult === 'OK';
? addParticipantResult === 'OK'
: addParticipantResult.messageSendResult === 'OK';
} }
participantData[participantId] = { participantData[participantId] = {

View file

@ -82,7 +82,7 @@ class GroupChat extends Chat {
!Array.isArray(participantIds) && (participantIds = [participantIds]); !Array.isArray(participantIds) && (participantIds = [participantIds]);
const groupWid = window.Store.WidFactory.createWid(groupId); const groupWid = window.Store.WidFactory.createWid(groupId);
const group = await window.Store.Chat.find(groupWid); const group = window.Store.Chat.get(groupWid) || (await window.Store.Chat.find(groupWid));
const participantWids = participantIds.map((p) => window.Store.WidFactory.createWid(p)); const participantWids = participantIds.map((p) => window.Store.WidFactory.createWid(p));
const errorCodes = { const errorCodes = {
@ -99,8 +99,8 @@ class GroupChat extends Chat {
}; };
await window.Store.GroupQueryAndUpdate({ id: groupId }); await window.Store.GroupQueryAndUpdate({ id: groupId });
const groupMetadata = group.groupMetadata;
const groupParticipants = groupMetadata?.participants; let groupParticipants = group.groupMetadata?.participants.serialize();
if (!groupParticipants) { if (!groupParticipants) {
return errorCodes.isGroupEmpty; return errorCodes.isGroupEmpty;
@ -110,6 +110,10 @@ class GroupChat extends Chat {
return errorCodes.iAmNotAdmin; return errorCodes.iAmNotAdmin;
} }
groupParticipants.map(({ id }) => {
return id.server === 'lid' ? window.Store.LidUtils.getPhoneNumber(id) : id;
});
const _getSleepTime = (sleep) => { const _getSleepTime = (sleep) => {
if (!Array.isArray(sleep) || sleep.length === 2 && sleep[0] === sleep[1]) { if (!Array.isArray(sleep) || sleep.length === 2 && sleep[0] === sleep[1]) {
return sleep; return sleep;
@ -130,7 +134,7 @@ class GroupChat extends Chat {
isInviteV4Sent: false isInviteV4Sent: false
}; };
if (groupParticipants.some(p => p.id._serialized === pId)) { if (groupParticipants.some(p => p._serialized === pId)) {
participantData[pId].code = 409; participantData[pId].code = 409;
participantData[pId].message = errorCodes[409]; participantData[pId].message = errorCodes[409];
continue; continue;
@ -143,7 +147,7 @@ class GroupChat extends Chat {
} }
const rpcResult = const rpcResult =
await window.WWebJS.getAddParticipantsRpcResult(groupMetadata, groupWid, pWid); await window.WWebJS.getAddParticipantsRpcResult(groupWid, pWid);
const { code: rpcResultCode } = rpcResult; const { code: rpcResultCode } = rpcResult;
participantData[pId].code = rpcResultCode; participantData[pId].code = rpcResultCode;
@ -155,7 +159,7 @@ class GroupChat extends Chat {
window.Store.Contact.gadd(pWid, { silent: true }); window.Store.Contact.gadd(pWid, { silent: true });
if (rpcResult.name === 'ParticipantRequestCodeCanBeSent' && if (rpcResult.name === 'ParticipantRequestCodeCanBeSent' &&
(userChat = await window.Store.Chat.find(pWid))) { (userChat = window.Store.Chat.get(pWid) || (await window.Store.Chat.find(pWid)))) {
const groupName = group.formattedTitle || group.name; const groupName = group.formattedTitle || group.name;
const res = await window.Store.GroupInviteV4.sendGroupInviteMessage( const res = await window.Store.GroupInviteV4.sendGroupInviteMessage(
userChat, userChat,
@ -166,9 +170,7 @@ class GroupChat extends Chat {
comment, comment,
await window.WWebJS.getProfilePicThumbToBase64(groupWid) await window.WWebJS.getProfilePicThumbToBase64(groupWid)
); );
isInviteV4Sent = window.compareWwebVersions(window.Debug.VERSION, '<', '2.2335.6') isInviteV4Sent = res.messageSendResult === 'OK';
? res === 'OK'
: res.messageSendResult === 'OK';
} }
participantData[pId].isInviteV4Sent = isInviteV4Sent; participantData[pId].isInviteV4Sent = isInviteV4Sent;

View file

@ -871,8 +871,8 @@ exports.LoadUtils = () => {
return dataUrl; return dataUrl;
return Object.assign(media, { return Object.assign(media, {
mimetype: options.mimeType, mimetype: options.mimetype,
data: dataUrl.replace(`data:${options.mimeType};base64,`, '') data: dataUrl.replace(`data:${options.mimetype};base64,`, '')
}); });
}; };
@ -941,30 +941,14 @@ exports.LoadUtils = () => {
return undefined; return undefined;
}; };
window.WWebJS.getAddParticipantsRpcResult = async (groupMetadata, groupWid, participantWid) => { window.WWebJS.getAddParticipantsRpcResult = async (groupWid, participantWid) => {
const participantLidArgs = groupMetadata?.isLidAddressingMode
? {
phoneNumber: participantWid,
lid: window.Store.LidUtils.getCurrentLid(participantWid)
}
: { phoneNumber: participantWid };
const iqTo = window.Store.WidToJid.widToGroupJid(groupWid); const iqTo = window.Store.WidToJid.widToGroupJid(groupWid);
const participantArgs = const participantArgs = [{
participantLidArgs.lid participantJid: window.Store.WidToJid.widToUserJid(participantWid)
? [{ }];
participantJid: window.Store.WidToJid.widToUserJid(participantLidArgs.lid),
phoneNumberMixinArgs: {
anyPhoneNumber: window.Store.WidToJid.widToUserJid(participantLidArgs.phoneNumber)
}
}]
: [{
participantJid: window.Store.WidToJid.widToUserJid(participantLidArgs.phoneNumber)
}];
let rpcResult, resultArgs; let rpcResult, resultArgs;
const isOldImpl = window.compareWwebVersions(window.Debug.VERSION, '<=', '2.2335.9');
const data = { const data = {
name: undefined, name: undefined,
code: undefined, code: undefined,
@ -974,12 +958,10 @@ exports.LoadUtils = () => {
try { try {
rpcResult = await window.Store.GroupParticipants.sendAddParticipantsRPC({ participantArgs, iqTo }); rpcResult = await window.Store.GroupParticipants.sendAddParticipantsRPC({ participantArgs, iqTo });
resultArgs = isOldImpl resultArgs = rpcResult.value.addParticipant[0]
? rpcResult.value.addParticipant[0].addParticipantsParticipantMixins .addParticipantsParticipantAddedOrNonRegisteredWaUserParticipantErrorLidResponseMixinGroup
: rpcResult.value.addParticipant[0] .value
.addParticipantsParticipantAddedOrNonRegisteredWaUserParticipantErrorLidResponseMixinGroup .addParticipantsParticipantMixins;
.value
.addParticipantsParticipantMixins;
} catch (err) { } catch (err) {
data.code = 400; data.code = 400;
return data; return data;