feat: groups share history mode - fix #2282
This commit is contained in:
1 parent
cc650fca3b
commit
0da9ef68cf
12 files changed
+185
-31
No files matched your search
@@ -362,13 +362,29 @@ export class GroupsController {
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
@Body() request: SettingsMemberShareHistoryMode,
|
||||
) {
|
||||
): Promise<boolean> {
|
||||
return session.setMemberShareHistoryMode(
|
||||
id,
|
||||
request.membersCanShareHistory,
|
||||
);
|
||||
}
|
||||
|
||||
@Get(':id/settings/security/member-share-history-mode')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
@CheckPolicies(CanSession(Action.Read, FromParam('session')))
|
||||
@ApiOperation({
|
||||
summary: 'Get settings - members can send message history to new members',
|
||||
description:
|
||||
'The group settings for whether members can share message history with new members, or only admins can.',
|
||||
})
|
||||
getMemberShareHistoryMode(
|
||||
@WorkingSessionParam session: WhatsappSession,
|
||||
@Param('id') id: string,
|
||||
): Promise<SettingsMemberShareHistoryMode> {
|
||||
return session.getMemberShareHistoryMode(id);
|
||||
}
|
||||
|
||||
@Put(':id/settings/security/membership-approval')
|
||||
@SessionApiParam
|
||||
@GroupIdApiParam
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
GroupIdInput,
|
||||
GroupJoinInput,
|
||||
GroupMembershipApprovalInput,
|
||||
GroupMemberShareHistoryInput,
|
||||
GroupParticipantsInput,
|
||||
GroupPictureInput,
|
||||
GroupsListInput,
|
||||
@@ -405,6 +406,47 @@ export class GroupTools extends McpController {
|
||||
});
|
||||
}
|
||||
|
||||
@Tool('groups-get-member-share-history', {
|
||||
title: 'Get member share history setting',
|
||||
description:
|
||||
'Get whether all members or only admins can share message history with new members',
|
||||
inputSchema: GroupIdInput,
|
||||
annotations: {
|
||||
readOnlyHint: true,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
},
|
||||
})
|
||||
async getMemberShareHistory({ session, id }: z.infer<typeof GroupIdInput>) {
|
||||
return this.textRequest({
|
||||
method: 'GET',
|
||||
url: `/api/${session}/groups/${id}/settings/security/member-share-history-mode`,
|
||||
});
|
||||
}
|
||||
|
||||
@Tool('groups-set-member-share-history', {
|
||||
title: 'Set member share history setting',
|
||||
description:
|
||||
'Allow all members or only admins to share message history with new members',
|
||||
inputSchema: GroupMemberShareHistoryInput,
|
||||
annotations: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
},
|
||||
})
|
||||
async setMemberShareHistory({
|
||||
session,
|
||||
id,
|
||||
...body
|
||||
}: z.infer<typeof GroupMemberShareHistoryInput>) {
|
||||
return this.textRequest({
|
||||
method: 'PUT',
|
||||
url: `/api/${session}/groups/${id}/settings/security/member-share-history-mode`,
|
||||
data: body,
|
||||
});
|
||||
}
|
||||
|
||||
@Tool('groups-get-join-requests', {
|
||||
title: 'Get pending requests to join the group',
|
||||
description: 'Get pending requests to join the group',
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
JoinGroupRequest,
|
||||
ParticipantsRequest,
|
||||
SettingsMembershipApproval,
|
||||
SettingsMemberShareHistoryMode,
|
||||
SettingsSecurityChangeInfo,
|
||||
SubjectRequest,
|
||||
} from '@waha/structures/groups.dto';
|
||||
@@ -72,3 +73,10 @@ export const GroupMembershipApprovalInput = DtoToZod(
|
||||
session: SessionField,
|
||||
id: GroupIdField,
|
||||
});
|
||||
|
||||
export const GroupMemberShareHistoryInput = DtoToZod(
|
||||
SettingsMemberShareHistoryMode,
|
||||
).extend({
|
||||
session: SessionField,
|
||||
id: GroupIdField,
|
||||
});
|
||||
@@ -114,6 +114,7 @@ import {
|
||||
GroupsListFields,
|
||||
ParticipantsRequest,
|
||||
SettingsMemberAddMode,
|
||||
SettingsMemberShareHistoryMode,
|
||||
SettingsMembershipApproval,
|
||||
SettingsSecurityChangeInfo,
|
||||
} from '../../structures/groups.dto';
|
||||
@@ -1025,7 +1026,16 @@ export abstract class WhatsappSession {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public setMemberShareHistoryMode(id, value) {
|
||||
public getMemberShareHistoryMode(
|
||||
id: string,
|
||||
): Promise<SettingsMemberShareHistoryMode> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
public setMemberShareHistoryMode(
|
||||
id: string,
|
||||
value: boolean,
|
||||
): Promise<boolean> {
|
||||
throw new NotImplementedByEngineError();
|
||||
}
|
||||
|
||||
|
||||
@@ -11726,6 +11726,15 @@ export namespace messages {
|
||||
responseSerialize: (message: Empty) => Buffer.from(message.serialize()),
|
||||
responseDeserialize: (bytes: Buffer) => Empty.deserialize(new Uint8Array(bytes))
|
||||
},
|
||||
SetGroupMemberShareHistoryMode: {
|
||||
path: "/messages.MessageService/SetGroupMemberShareHistoryMode",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestSerialize: (message: JidBoolRequest) => Buffer.from(message.serialize()),
|
||||
requestDeserialize: (bytes: Buffer) => JidBoolRequest.deserialize(new Uint8Array(bytes)),
|
||||
responseSerialize: (message: Empty) => Buffer.from(message.serialize()),
|
||||
responseDeserialize: (bytes: Buffer) => Empty.deserialize(new Uint8Array(bytes))
|
||||
},
|
||||
UpdateGroupParticipants: {
|
||||
path: "/messages.MessageService/UpdateGroupParticipants",
|
||||
requestStream: false,
|
||||
@@ -12144,6 +12153,7 @@ export namespace messages {
|
||||
abstract SetGroupLocked(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract SetGroupAnnounce(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract SetGroupMemberAddMode(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract SetGroupMemberShareHistoryMode(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract UpdateGroupParticipants(call: grpc_1.ServerUnaryCall<UpdateParticipantsRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
|
||||
abstract SetGroupJoinApprovalMode(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
|
||||
abstract GetGroupRequestParticipants(call: grpc_1.ServerUnaryCall<JidRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
|
||||
@@ -12279,6 +12289,9 @@ export namespace messages {
|
||||
SetGroupMemberAddMode: GrpcUnaryServiceInterface<JidBoolRequest, Empty> = (message: JidBoolRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Empty>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Empty>, callback?: grpc_1.requestCallback<Empty>): grpc_1.ClientUnaryCall => {
|
||||
return super.SetGroupMemberAddMode(message, metadata, options, callback);
|
||||
};
|
||||
SetGroupMemberShareHistoryMode: GrpcUnaryServiceInterface<JidBoolRequest, Empty> = (message: JidBoolRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Empty>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Empty>, callback?: grpc_1.requestCallback<Empty>): grpc_1.ClientUnaryCall => {
|
||||
return super.SetGroupMemberShareHistoryMode(message, metadata, options, callback);
|
||||
};
|
||||
UpdateGroupParticipants: GrpcUnaryServiceInterface<UpdateParticipantsRequest, JsonList> = (message: UpdateParticipantsRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, options?: grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, callback?: grpc_1.requestCallback<JsonList>): grpc_1.ClientUnaryCall => {
|
||||
return super.UpdateGroupParticipants(message, metadata, options, callback);
|
||||
};
|
||||
|
||||
@@ -1073,6 +1073,18 @@ setGroupMemberAddMode: {
|
||||
responseDeserialize: deserialize_messages_Empty,
|
||||
},
|
||||
// who can add members - true - all members, false - admins only
|
||||
setGroupMemberShareHistoryMode: {
|
||||
path: '/messages.MessageService/SetGroupMemberShareHistoryMode',
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestType: gows_pb.JidBoolRequest,
|
||||
responseType: gows_pb.Empty,
|
||||
requestSerialize: serialize_messages_JidBoolRequest,
|
||||
requestDeserialize: deserialize_messages_JidBoolRequest,
|
||||
responseSerialize: serialize_messages_Empty,
|
||||
responseDeserialize: deserialize_messages_Empty,
|
||||
},
|
||||
// who can share message history with new members - true - all members, false - admins only
|
||||
updateGroupParticipants: {
|
||||
path: '/messages.MessageService/UpdateGroupParticipants',
|
||||
requestStream: false,
|
||||
|
||||
@@ -133,6 +133,7 @@ import {
|
||||
Participant,
|
||||
ParticipantsRequest,
|
||||
SettingsMemberAddMode,
|
||||
SettingsMemberShareHistoryMode,
|
||||
SettingsMembershipApproval,
|
||||
SettingsSecurityChangeInfo,
|
||||
} from '@waha/structures/groups.dto';
|
||||
@@ -1804,6 +1805,30 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
return;
|
||||
}
|
||||
|
||||
public async getMemberShareHistoryMode(
|
||||
id: string,
|
||||
): Promise<SettingsMemberShareHistoryMode> {
|
||||
const group = await this.getGroup(id);
|
||||
return {
|
||||
membersCanShareHistory:
|
||||
group.MemberShareHistoryMode === 'all_member_share',
|
||||
};
|
||||
}
|
||||
|
||||
@Activity()
|
||||
public async setMemberShareHistoryMode(
|
||||
id: string,
|
||||
value: boolean,
|
||||
): Promise<boolean> {
|
||||
const req = new messages.JidBoolRequest({
|
||||
session: this.session,
|
||||
jid: id,
|
||||
value: value,
|
||||
});
|
||||
await promisify(this.client.SetGroupMemberShareHistoryMode)(req);
|
||||
return true;
|
||||
}
|
||||
|
||||
public async getMembershipApprovalMode(
|
||||
id: string,
|
||||
): Promise<SettingsMembershipApproval> {
|
||||
|
||||
@@ -101,6 +101,7 @@ export interface GroupInfoFull {
|
||||
IsAnnounce: boolean; // specifies whether only admins can send messages in the group
|
||||
Participants: GOWSGroupParticipant[];
|
||||
MemberAddMode: string; // all_member_add | admin_add
|
||||
MemberShareHistoryMode: string; // all_member_share | admin_share
|
||||
IsJoinApprovalRequired: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ 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,
|
||||
@@ -298,14 +297,6 @@ 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;
|
||||
@@ -2248,23 +2239,21 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
return await this.sock.groupMemberAddMode(id, mode);
|
||||
}
|
||||
|
||||
public async getMemberShareHistoryMode(
|
||||
id: string,
|
||||
): Promise<SettingsMemberShareHistoryMode> {
|
||||
const group = await this.getGroup(id);
|
||||
return { membersCanShareHistory: !!group.memberShareHistoryMode };
|
||||
}
|
||||
|
||||
@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 setMemberShareHistoryMode(
|
||||
id: string,
|
||||
value: boolean,
|
||||
): Promise<boolean> {
|
||||
const mode = value ? 'all_member_share' : 'admin_share';
|
||||
await this.sock.groupMemberShareHistoryMode(id, mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
public async getMembershipApprovalMode(
|
||||
|
||||
@@ -117,6 +117,7 @@ import {
|
||||
GroupSortField,
|
||||
ParticipantsRequest,
|
||||
SettingsMemberAddMode,
|
||||
SettingsMemberShareHistoryMode,
|
||||
SettingsMembershipApproval,
|
||||
SettingsSecurityChangeInfo,
|
||||
} from '@waha/structures/groups.dto';
|
||||
@@ -1757,6 +1758,28 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
|
||||
return groupChat.setAddMembersAdminsOnly(!value);
|
||||
}
|
||||
|
||||
public async getMemberShareHistoryMode(
|
||||
id: string,
|
||||
): Promise<SettingsMemberShareHistoryMode> {
|
||||
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
|
||||
return {
|
||||
membersCanShareHistory:
|
||||
// @ts-ignore
|
||||
groupChat.groupMetadata.memberShareGroupHistoryMode ===
|
||||
'all_member_share',
|
||||
};
|
||||
}
|
||||
|
||||
@Activity()
|
||||
public async setMemberShareHistoryMode(
|
||||
id: string,
|
||||
value: boolean,
|
||||
): Promise<boolean> {
|
||||
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
|
||||
// The library setter is inverted - it takes "adminsOnly"
|
||||
return groupChat.setShareHistoryAdminsOnly(!value);
|
||||
}
|
||||
|
||||
@Activity()
|
||||
public async getMembershipApprovalMode(
|
||||
id: string,
|
||||
|
||||
@@ -178,6 +178,7 @@ import {
|
||||
NormalizeJoinRequestMethod,
|
||||
ParticipantsRequest,
|
||||
SettingsMemberAddMode,
|
||||
SettingsMemberShareHistoryMode,
|
||||
SettingsMembershipApproval,
|
||||
SettingsSecurityChangeInfo,
|
||||
} from '@waha/structures/groups.dto';
|
||||
@@ -1624,6 +1625,20 @@ export class WhatsappSessionWPPCore extends WhatsappSession {
|
||||
);
|
||||
}
|
||||
|
||||
public async getMemberShareHistoryMode(
|
||||
id: string,
|
||||
): Promise<SettingsMemberShareHistoryMode> {
|
||||
const groupId = await this.hooks.wid.chat.promise(
|
||||
id,
|
||||
'getMemberShareHistoryMode',
|
||||
);
|
||||
const group = await this.wpp!.getChatById(groupId);
|
||||
// Undocumented property - 'all_member_share' or 'admin_share'
|
||||
// @ts-ignore
|
||||
const mode = group?.groupMetadata?.memberShareGroupHistoryMode;
|
||||
return { membersCanShareHistory: mode === 'all_member_share' };
|
||||
}
|
||||
|
||||
public async getMembershipApprovalMode(
|
||||
id: string,
|
||||
): Promise<SettingsMembershipApproval> {
|
||||
|
||||
@@ -7,7 +7,7 @@ __metadata:
|
||||
|
||||
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-2026-04-28":
|
||||
version: 7.0.0-rc14
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=93433a380977fce781d25c5e40d8f12d8ea8109e"
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=14ed18cd9fc524309fbecaed4949ea73eaf6761e"
|
||||
dependencies:
|
||||
"@cacheable/node-cache": "npm:^1.4.0"
|
||||
"@hapi/boom": "npm:^9.1.3"
|
||||
@@ -32,7 +32,7 @@ __metadata:
|
||||
optional: true
|
||||
link-preview-js:
|
||||
optional: true
|
||||
checksum: 10/3fdf6e7eea36d474a46c70e645872f588d3c47dcdc99898477be1665302844aa3c5da221cd9773380ea66d28deb9e9e565a1507323be5840eba23352c7707583
|
||||
checksum: 10/d7c290e64065517c43094f5700daf1230dfa54254aa2965d8efca94bdefbd464904a390f16d695c0305a0e7f408acd9fda566bacb30dc493ff563fcb06892873
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -14381,7 +14381,7 @@ __metadata:
|
||||
|
||||
"whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-main-2026-06-26":
|
||||
version: 1.34.7
|
||||
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=a95362738822bcb670f9e20f79acaf83304a6a2d"
|
||||
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=7bcd3528538372f9420a63472491513066993090"
|
||||
dependencies:
|
||||
archiver: "npm:7.0.1"
|
||||
fluent-ffmpeg: "npm:2.1.3"
|
||||
@@ -14398,7 +14398,7 @@ __metadata:
|
||||
optional: true
|
||||
unzipper:
|
||||
optional: true
|
||||
checksum: 10/ee21c2d7cf3e94eccc931fca7f386aaf6fd5ba4d8f362dd79df8f45fab22298538eaedb5fa5c4ae80a622e51a229601f20fd41c90a781428ad681ce821861de6
|
||||
checksum: 10/52b776bd9cde2799fed01ca507f8a43e17cce11254fa58cc3e96fa40f206532311050a38d6c25ee895616c9c39286615e6513c952667b6bd8610d5de03068cdb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in new issue
Block a user