From cc650fca3bb8ebd756f4e74d29a8a67b0d66dff2 Mon Sep 17 00:00:00 2001 From: Alison White <48805279+alisonmwhite@users.noreply.github.com> Date: Wed, 30 Sep 2026 02:11:02 -0700 Subject: [PATCH] feat(NOWEB): expose group member-share-history-mode as a settable endpoint (#2283) --- src/api/groups.controller.ts | 23 ++++++++++++++++ src/core/abc/session.abc.ts | 4 +++ src/core/engines/noweb/session.noweb.core.ts | 29 ++++++++++++++++++++ src/structures/groups.dto.ts | 5 ++++ 4 files changed, 61 insertions(+) diff --git a/src/api/groups.controller.ts b/src/api/groups.controller.ts index c30070e2..3b670a09 100644 --- a/src/api/groups.controller.ts +++ b/src/api/groups.controller.ts @@ -41,6 +41,7 @@ import { JoinGroupResponse, ParticipantsRequest, SettingsMemberAddMode, + SettingsMemberShareHistoryMode, SettingsMembershipApproval, SettingsSecurityChangeInfo, SubjectRequest, @@ -346,6 +347,28 @@ export class GroupsController { return session.getMemberAddMode(id); } + @Put(':id/settings/security/member-share-history-mode') + @SessionApiParam + @GroupIdApiParam + @CheckPolicies(CanSession(Action.Send, FromParam('session'))) + @ApiOperation({ + summary: + 'Update settings - members can send message history to new members', + description: + 'Updates the group settings for whether members can share message history with new members, or only admins can.', + }) + @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) + setMemberShareHistoryMode( + @WorkingSessionParam session: WhatsappSession, + @Param('id') id: string, + @Body() request: SettingsMemberShareHistoryMode, + ) { + return session.setMemberShareHistoryMode( + id, + request.membersCanShareHistory, + ); + } + @Put(':id/settings/security/membership-approval') @SessionApiParam @GroupIdApiParam diff --git a/src/core/abc/session.abc.ts b/src/core/abc/session.abc.ts index 4ac708f3..a35de7b3 100644 --- a/src/core/abc/session.abc.ts +++ b/src/core/abc/session.abc.ts @@ -1025,6 +1025,10 @@ export abstract class WhatsappSession { throw new NotImplementedByEngineError(); } + public setMemberShareHistoryMode(id, value) { + throw new NotImplementedByEngineError(); + } + public getMembershipApprovalMode( id: string, ): Promise { diff --git a/src/core/engines/noweb/session.noweb.core.ts b/src/core/engines/noweb/session.noweb.core.ts index 41a786e0..fa73994e 100644 --- a/src/core/engines/noweb/session.noweb.core.ts +++ b/src/core/engines/noweb/session.noweb.core.ts @@ -28,6 +28,7 @@ import makeWASocket, { import { WACallEvent } from '@adiwajshing/baileys/lib/Types/Call'; import { BaileysEventMap } from '@adiwajshing/baileys/lib/Types/Events'; import { GroupMetadata } from '@adiwajshing/baileys/lib/Types/GroupMetadata'; +import { executeWMexQuery } from '@adiwajshing/baileys/lib/Socket/mex'; import { Label as NOWEBLabel, LabelActionBody, @@ -168,6 +169,7 @@ import { GroupParticipant, ParticipantsRequest, SettingsMemberAddMode, + SettingsMemberShareHistoryMode, SettingsMembershipApproval, SettingsSecurityChangeInfo, } from '@waha/structures/groups.dto'; @@ -296,6 +298,14 @@ export interface NowebConfig { waVersion: WAVersion; } +// WhatsApp Web MEX (w:mex) doc/query_id for the group property mutation that sets +// "members can send message history to new members". Captured from WhatsApp Web's +// WAWebMexUpdateGroupPropertyJobMutation on 2026-09-25 (see whatsapp-rust +// wacore/src/iq/mex_operations.rs, mod update_group_property). WhatsApp rotates these +// ids when Web is updated -- if this mutation starts failing, re-capture the query_id +// from a fresh WhatsApp Web session before assuming the endpoint itself is broken. +const MEX_QUERY_ID_UPDATE_GROUP_PROPERTY = '9418211574894172'; + export class WhatsappSessionNoWebCore extends WhatsappSession { private START_ATTEMPT_DELAY_SECONDS = 2; private AUTO_RESTART_AFTER_SECONDS = 28 * 60; @@ -2238,6 +2248,25 @@ export class WhatsappSessionNoWebCore extends WhatsappSession { return await this.sock.groupMemberAddMode(id, mode); } + @Activity() + public async setMemberShareHistoryMode(id, value) { + const mode = value ? 'ALL_MEMBER_SHARE' : 'ADMIN_SHARE'; + const result = await executeWMexQuery<{ state?: string }>( + { group_id: id, update: { member_share_group_history_mode: mode } }, + MEX_QUERY_ID_UPDATE_GROUP_PROPERTY, + 'xwa2_group_update_property', + this.sock.query, + this.sock.generateMessageTag, + ); + if (result?.state !== 'ACTIVE') { + throw new Error( + `Failed to set member share history mode for group '${id}': ` + + `unexpected state '${result?.state}'`, + ); + } + return result; + } + public async getMembershipApprovalMode( id: string, ): Promise { diff --git a/src/structures/groups.dto.ts b/src/structures/groups.dto.ts index 30bee795..d7959695 100644 --- a/src/structures/groups.dto.ts +++ b/src/structures/groups.dto.ts @@ -31,6 +31,11 @@ export class SettingsMemberAddMode { membersCanAddNewMember: boolean = true; } +export class SettingsMemberShareHistoryMode { + @IsBoolean() + membersCanShareHistory: boolean = true; +} + export class SettingsMembershipApproval { @IsBoolean() newMembersApprovalRequired: boolean = false;