diff --git a/packages/core/src/bridge/apis/group-admin.ts b/packages/core/src/bridge/apis/group-admin.ts index 0e63c89b..42f8fb57 100644 --- a/packages/core/src/bridge/apis/group-admin.ts +++ b/packages/core/src/bridge/apis/group-admin.ts @@ -39,6 +39,8 @@ import type { BridgeContext } from '../bridge-context'; export type GroupAdminSettings = { add_type: number; + group_question: string; + group_answer: string; robot_member_switch: number; robot_member_examine: number; member_invite_policy: GroupMemberInvitePolicy; @@ -77,6 +79,8 @@ export class GroupAdminApi { const permissions = decodeGroupMemberPermissions(privilegeFlag); return { add_type: results.addType ?? 0, + group_question: results.question ?? '', + group_answer: results.answer ?? '', robot_member_switch: robot.robotMemberSwitch, robot_member_examine: robot.robotMemberExamine, member_invite_policy: decodeMemberInvitePolicy(privilegeFlag), @@ -97,8 +101,13 @@ export class GroupAdminApi { return MuteAll.invoke(this.ctx, { groupId, enable }); } - setAddOption(groupId: number, addType: number): Promise { - return SetAddOption.invoke(this.ctx, { groupId, addType }); + setAddOption( + groupId: number, + addType: number, + groupQuestion?: string, + groupAnswer?: string, + ): Promise { + return SetAddOption.invoke(this.ctx, { groupId, addType, groupQuestion, groupAnswer }); } setSearch(groupId: number, noFingerOpen?: number, noCodeFingerOpen?: number): Promise { diff --git a/packages/core/tests/actions/group-admin.test.ts b/packages/core/tests/actions/group-admin.test.ts index 15b6e30f..17ac73ba 100644 --- a/packages/core/tests/actions/group-admin.test.ts +++ b/packages/core/tests/actions/group-admin.test.ts @@ -231,11 +231,24 @@ describe('apis/group-admin', () => { const addOptEnv = protobuf_decode>(bridge.sendRawPacket.mock.calls[4]![1]); expect(addOptEnv.body).toMatchObject({ groupUin: 1n, settings: { addType: 2 } }); + expect(addOptEnv.body?.settings?.groupQuestion ?? undefined).toBeUndefined(); const searchEnv = protobuf_decode>(bridge.sendRawPacket.mock.calls[5]![1]); expect(searchEnv.body?.groupUin).toBe(1n); }); + it('setAddOption forwards question and answer for type 4', async () => { + const bridge = mockBridge(); + await new GroupAdminApi(bridge as any).setAddOption(12345, 4, 'how', '42'); + const envelope = protobuf_decode>( + bridge.sendRawPacket.mock.calls[0]![1], + ); + expect(envelope.body).toMatchObject({ + groupUin: 12345n, + settings: { addType: 4, groupQuestion: 'how', groupAnswer: '42' }, + }); + }); + it('setAddRequest picks _1 / _2 based on filtered flag', async () => { const bridge = mockBridge(); await new GroupAdminApi(bridge as any).setAddRequest(12345, 5, 1, true, 'ok', false); @@ -446,6 +459,8 @@ describe('apis/group-admin', () => { if (cmd === 'OidbSvcTrpcTcp.0x88d_0') { return packAdminDetail({ addType: 2, + question: 'how', + answer: '42', privilegeFlag: 0x84018001, groupFlagExt4: 0x80000005, noFingerOpen: 1, @@ -460,6 +475,8 @@ describe('apis/group-admin', () => { const out = await new GroupAdminApi(bridge as any).getAdminSettings(12345); expect(out).toEqual({ add_type: 2, + group_question: 'how', + group_answer: '42', robot_member_switch: 1, robot_member_examine: 2, member_invite_policy: 'disabled', @@ -490,6 +507,8 @@ describe('apis/group-admin', () => { await expect(new GroupAdminApi(bridge as any).getAdminSettings(12345)).resolves.toEqual({ add_type: 0, + group_question: '', + group_answer: '', robot_member_switch: 0, robot_member_examine: 0, member_invite_policy: 'require_approval', diff --git a/packages/mcp/src/generated/catalog.json b/packages/mcp/src/generated/catalog.json index c1a52f35..6e227d7c 100644 --- a/packages/mcp/src/generated/catalog.json +++ b/packages/mcp/src/generated/catalog.json @@ -3874,6 +3874,14 @@ "type": "integer", "description": "加群选项(同 set_group_add_option.add_type)" }, + "group_question": { + "type": "string", + "description": "加群问题(同 set_group_add_option.group_question)" + }, + "group_answer": { + "type": "string", + "description": "加群答案(同 set_group_add_option.group_answer)" + }, "robot_member_switch": { "type": "integer", "description": "机器人加群开关(同 set_group_robot_add_option)" @@ -3919,6 +3927,8 @@ }, "required": [ "add_type", + "group_question", + "group_answer", "robot_member_switch", "robot_member_examine", "member_invite_policy", @@ -9617,6 +9627,22 @@ "minimum": 0 }, "default": 0 + }, + { + "name": "group_question", + "type": "string", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "group_answer", + "type": "string", + "required": false, + "schema": { + "type": "string" + } } ], "invariants": [], @@ -9633,6 +9659,12 @@ "type": "integer", "minimum": 0, "default": 0 + }, + "group_question": { + "type": "string" + }, + "group_answer": { + "type": "string" } }, "required": [ diff --git a/packages/mcp/src/generated/catalog.ts b/packages/mcp/src/generated/catalog.ts index 783923aa..c9658c20 100644 --- a/packages/mcp/src/generated/catalog.ts +++ b/packages/mcp/src/generated/catalog.ts @@ -3877,6 +3877,14 @@ export const ACTIONS: CatalogAction[] = [ "type": "integer", "description": "加群选项(同 set_group_add_option.add_type)" }, + "group_question": { + "type": "string", + "description": "加群问题(同 set_group_add_option.group_question)" + }, + "group_answer": { + "type": "string", + "description": "加群答案(同 set_group_add_option.group_answer)" + }, "robot_member_switch": { "type": "integer", "description": "机器人加群开关(同 set_group_robot_add_option)" @@ -3922,6 +3930,8 @@ export const ACTIONS: CatalogAction[] = [ }, "required": [ "add_type", + "group_question", + "group_answer", "robot_member_switch", "robot_member_examine", "member_invite_policy", @@ -9620,6 +9630,22 @@ export const ACTIONS: CatalogAction[] = [ "minimum": 0 }, "default": 0 + }, + { + "name": "group_question", + "type": "string", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "group_answer", + "type": "string", + "required": false, + "schema": { + "type": "string" + } } ], "invariants": [], @@ -9636,6 +9662,12 @@ export const ACTIONS: CatalogAction[] = [ "type": "integer", "minimum": 0, "default": 0 + }, + "group_question": { + "type": "string" + }, + "group_answer": { + "type": "string" } }, "required": [ diff --git a/packages/onebot/src/actions/group-admin.ts b/packages/onebot/src/actions/group-admin.ts index c76939f2..98db5d8c 100644 --- a/packages/onebot/src/actions/group-admin.ts +++ b/packages/onebot/src/actions/group-admin.ts @@ -45,9 +45,15 @@ export const actions = [ groupAction({ name: 'set_group_add_option', summary: '设置加群选项', - params: { add_type: f.int({ min: 0 }).default(0) }, + params: { + add_type: f.int({ min: 0 }).default(0), + group_question: f.string().optional(), + group_answer: f.string().optional(), + }, run: async (p, ctx) => { - await ctx.bridge.apis.groupAdmin.setAddOption(p.group_id, p.add_type); + await ctx.bridge.apis.groupAdmin.setAddOption( + p.group_id, p.add_type, p.group_question, p.group_answer, + ); return okResponse(); }, }), @@ -124,6 +130,8 @@ export const actions = [ type: 'object', properties: { add_type: { type: 'integer', description: '加群选项(同 set_group_add_option.add_type)' }, + group_question: { type: 'string', description: '加群问题(同 set_group_add_option.group_question)' }, + group_answer: { type: 'string', description: '加群答案(同 set_group_add_option.group_answer)' }, robot_member_switch: { type: 'integer', description: '机器人加群开关(同 set_group_robot_add_option)' }, robot_member_examine: { type: 'integer', description: '机器人加群审核(同 set_group_robot_add_option)' }, member_invite_policy: { @@ -140,6 +148,8 @@ export const actions = [ }, required: [ 'add_type', + 'group_question', + 'group_answer', 'robot_member_switch', 'robot_member_examine', 'member_invite_policy', diff --git a/packages/onebot/tests/actions-group-admin.test.ts b/packages/onebot/tests/actions-group-admin.test.ts index 58c1cc01..618b387a 100644 --- a/packages/onebot/tests/actions-group-admin.test.ts +++ b/packages/onebot/tests/actions-group-admin.test.ts @@ -454,18 +454,18 @@ describe('set_group_add_option parse', () => { it('defaults add_type to 0 and keeps a present 0', () => { expect(setGroupAddOption.parse({ group_id: 12345 })).toEqual({ ok: true, - value: { group_id: 12345, add_type: 0 }, + value: { group_id: 12345, add_type: 0, group_question: undefined, group_answer: undefined }, }); expect(setGroupAddOption.parse({ group_id: 12345, add_type: 0 })).toEqual({ ok: true, - value: { group_id: 12345, add_type: 0 }, + value: { group_id: 12345, add_type: 0, group_question: undefined, group_answer: undefined }, }); }); it('accepts a positive add_type and rejects a negative one', () => { expect(setGroupAddOption.parse({ group_id: 12345, add_type: '2' })).toEqual({ ok: true, - value: { group_id: 12345, add_type: 2 }, + value: { group_id: 12345, add_type: 2, group_question: undefined, group_answer: undefined }, }); expect(setGroupAddOption.parse({ group_id: 12345, add_type: -1 })).toEqual({ ok: false, @@ -473,6 +473,23 @@ describe('set_group_add_option parse', () => { reason: 'must be >= 0', }); }); + + it('keeps optional question and answer when present', () => { + expect(setGroupAddOption.parse({ + group_id: 12345, + add_type: 4, + group_question: 'q', + group_answer: 'a', + })).toEqual({ + ok: true, + value: { + group_id: 12345, + add_type: 4, + group_question: 'q', + group_answer: 'a', + }, + }); + }); }); describe('set_group_add_option toHandler', () => { @@ -483,7 +500,7 @@ describe('set_group_add_option toHandler', () => { await expect(setGroupAddOption.toHandler(ctx)({ group_id: 12345 })) .resolves.toEqual({ status: 'ok', retcode: 0, data: null }); - expect(setAddOption.mock.calls).toEqual([[12345, 0]]); + expect(setAddOption.mock.calls).toEqual([[12345, 0, undefined, undefined]]); }); it('forwards an explicit add_type', async () => { @@ -495,7 +512,21 @@ describe('set_group_add_option toHandler', () => { add_type: 3, })).resolves.toEqual({ status: 'ok', retcode: 0, data: null }); - expect(setAddOption.mock.calls).toEqual([[941657197, 3]]); + expect(setAddOption.mock.calls).toEqual([[941657197, 3, undefined, undefined]]); + }); + + it('forwards question and answer', async () => { + const setAddOption = vi.fn(async () => {}); + const { ctx } = adminCtx({ setAddOption }); + + await expect(setGroupAddOption.toHandler(ctx)({ + group_id: 941657197, + add_type: 4, + group_question: 'q', + group_answer: 'a', + })).resolves.toEqual({ status: 'ok', retcode: 0, data: null }); + + expect(setAddOption.mock.calls).toEqual([[941657197, 4, 'q', 'a']]); }); }); @@ -780,6 +811,8 @@ describe('get_group_admin_settings toHandler', () => { it('forwards group_id and returns the current settings', async () => { const settings = { add_type: 2, + group_question: 'q', + group_answer: 'a', robot_member_switch: 1, robot_member_examine: 0, member_invite_policy: 'require_approval', diff --git a/packages/sdk/src/types/params.ts b/packages/sdk/src/types/params.ts index 9ac0f156..c52b2bc9 100644 --- a/packages/sdk/src/types/params.ts +++ b/packages/sdk/src/types/params.ts @@ -88,6 +88,8 @@ export interface SetGroupWholeBanParams extends GroupIdParams { export interface SetGroupAddOptionParams extends GroupIdParams { add_type: number; + group_question?: string; + group_answer?: string; } export interface SetGroupAdminParams extends GroupIdParams { diff --git a/packages/sdk/src/types/results.ts b/packages/sdk/src/types/results.ts index abc22166..4e6c385f 100644 --- a/packages/sdk/src/types/results.ts +++ b/packages/sdk/src/types/results.ts @@ -219,6 +219,8 @@ export interface GroupAtAllRemainInfo { export type GroupAdminSettings = { add_type: number; + group_question: string; + group_answer: string; robot_member_switch: number; robot_member_examine: number; member_invite_policy: 'disabled' | 'require_approval' | 'no_approval' | 'no_approval_under_100';