feat(onebot): expose administrator permission actions
Expose administrator permission controls through OneBot, the SDK, and MCP. Document limits and unknown states, and validate public request and result contracts.
This commit is contained in:
@@ -6510,6 +6510,111 @@
|
||||
},
|
||||
"category": "扩展"
|
||||
},
|
||||
{
|
||||
"name": "get_group_admin_permissions",
|
||||
"aliases": [],
|
||||
"summary": "读取指定管理员的撤回、移除成员及每日移除上限",
|
||||
"returns": "服务器返回的管理员权限;未返回或未指定的开关为 null。每日上限仅在移除权限开启时返回,0 表示不限。",
|
||||
"returnsSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"recall_member_message": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
],
|
||||
"description": "撤回成员消息;null 表示服务器未指定"
|
||||
},
|
||||
"kick_member": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
],
|
||||
"description": "移除群成员;null 表示服务器未指定"
|
||||
},
|
||||
"kick_member_per_day": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"description": "每日可移除人数,0 不限;权限关闭或未指定时为 null"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"group_id",
|
||||
"user_id",
|
||||
"recall_member_message",
|
||||
"kick_member",
|
||||
"kick_member_per_day"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"summary": "读取管理员权限",
|
||||
"params": {
|
||||
"group_id": 20001,
|
||||
"user_id": 10001
|
||||
},
|
||||
"notes": "user_id 为目标管理员 QQ 号;不包含接收验证消息开关。"
|
||||
}
|
||||
],
|
||||
"readOnly": true,
|
||||
"params": [
|
||||
{
|
||||
"name": "group_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "group_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "群号"
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "member_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "QQ 号"
|
||||
}
|
||||
],
|
||||
"invariants": [],
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "群号",
|
||||
"x-role": "group_id"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "QQ 号",
|
||||
"x-role": "member_id"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"group_id",
|
||||
"user_id"
|
||||
],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"category": "群管理"
|
||||
},
|
||||
{
|
||||
"name": "get_group_admin_settings",
|
||||
"aliases": [],
|
||||
@@ -16515,6 +16620,198 @@
|
||||
},
|
||||
"category": "群管理"
|
||||
},
|
||||
{
|
||||
"name": "set_group_admin_permissions",
|
||||
"aliases": [],
|
||||
"summary": "设置指定管理员的撤回和移除成员权限",
|
||||
"returnsSchema": {
|
||||
"type": "null",
|
||||
"description": "服务器确认请求后 data 为 null;不代表已经过客户端回读验证。可用 get_group_admin_permissions 查询。"
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"summary": "允许管理员每日移除至多 10 人",
|
||||
"params": {
|
||||
"group_id": 20001,
|
||||
"user_id": 10001,
|
||||
"kick_member": true,
|
||||
"kick_member_per_day": 10
|
||||
},
|
||||
"notes": "需要当前账号具有修改权限;不会授予管理员角色。仅修改显式字段。开启移除必须提供上限,0 表示不限;修改上限需同时传 kick_member=true。"
|
||||
}
|
||||
],
|
||||
"readOnly": false,
|
||||
"params": [
|
||||
{
|
||||
"name": "group_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "group_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "群号"
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "member_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "QQ 号"
|
||||
},
|
||||
{
|
||||
"name": "recall_member_message",
|
||||
"type": "bool",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kick_member",
|
||||
"type": "bool",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kick_member_per_day",
|
||||
"type": "int",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 200
|
||||
}
|
||||
}
|
||||
],
|
||||
"invariants": [
|
||||
"at least one of: recall_member_message, kick_member",
|
||||
"kick_member=true requires kick_member_per_day: 0, 5, 10, 20, 50, 100 or 200",
|
||||
"kick_member_per_day requires kick_member=true"
|
||||
],
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "群号",
|
||||
"x-role": "group_id"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "QQ 号",
|
||||
"x-role": "member_id"
|
||||
},
|
||||
"recall_member_message": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"kick_member": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"kick_member_per_day": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 200
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"group_id",
|
||||
"user_id"
|
||||
],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"category": "群管理"
|
||||
},
|
||||
{
|
||||
"name": "set_group_admin_receive_verify",
|
||||
"aliases": [],
|
||||
"summary": "设置指定管理员是否接收加群验证消息",
|
||||
"returnsSchema": {
|
||||
"type": "null",
|
||||
"description": "服务器响应确认目标群和管理员后 data 为 null;未确认目标时返回错误。"
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"summary": "开启接收验证消息",
|
||||
"params": {
|
||||
"group_id": 20001,
|
||||
"user_id": 10001,
|
||||
"enable": true
|
||||
},
|
||||
"notes": "user_id 为目标管理员 QQ 号;需要当前账号具有修改权限。独立于撤回和移除成员权限。"
|
||||
}
|
||||
],
|
||||
"readOnly": false,
|
||||
"params": [
|
||||
{
|
||||
"name": "group_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "group_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "群号"
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "member_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "QQ 号"
|
||||
},
|
||||
{
|
||||
"name": "enable",
|
||||
"type": "bool",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
],
|
||||
"invariants": [],
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "群号",
|
||||
"x-role": "group_id"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "QQ 号",
|
||||
"x-role": "member_id"
|
||||
},
|
||||
"enable": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"group_id",
|
||||
"user_id",
|
||||
"enable"
|
||||
],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"category": "群管理"
|
||||
},
|
||||
{
|
||||
"name": "set_group_album_media_like",
|
||||
"aliases": [],
|
||||
@@ -20428,7 +20725,7 @@
|
||||
},
|
||||
{
|
||||
"category": "群管理",
|
||||
"count": 21
|
||||
"count": 24
|
||||
},
|
||||
{
|
||||
"category": "群文件",
|
||||
|
||||
@@ -6513,6 +6513,111 @@ export const ACTIONS: CatalogAction[] = [
|
||||
},
|
||||
"category": "扩展"
|
||||
},
|
||||
{
|
||||
"name": "get_group_admin_permissions",
|
||||
"aliases": [],
|
||||
"summary": "读取指定管理员的撤回、移除成员及每日移除上限",
|
||||
"returns": "服务器返回的管理员权限;未返回或未指定的开关为 null。每日上限仅在移除权限开启时返回,0 表示不限。",
|
||||
"returnsSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"recall_member_message": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
],
|
||||
"description": "撤回成员消息;null 表示服务器未指定"
|
||||
},
|
||||
"kick_member": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
],
|
||||
"description": "移除群成员;null 表示服务器未指定"
|
||||
},
|
||||
"kick_member_per_day": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"description": "每日可移除人数,0 不限;权限关闭或未指定时为 null"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"group_id",
|
||||
"user_id",
|
||||
"recall_member_message",
|
||||
"kick_member",
|
||||
"kick_member_per_day"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"summary": "读取管理员权限",
|
||||
"params": {
|
||||
"group_id": 20001,
|
||||
"user_id": 10001
|
||||
},
|
||||
"notes": "user_id 为目标管理员 QQ 号;不包含接收验证消息开关。"
|
||||
}
|
||||
],
|
||||
"readOnly": true,
|
||||
"params": [
|
||||
{
|
||||
"name": "group_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "group_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "群号"
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "member_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "QQ 号"
|
||||
}
|
||||
],
|
||||
"invariants": [],
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "群号",
|
||||
"x-role": "group_id"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "QQ 号",
|
||||
"x-role": "member_id"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"group_id",
|
||||
"user_id"
|
||||
],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"category": "群管理"
|
||||
},
|
||||
{
|
||||
"name": "get_group_admin_settings",
|
||||
"aliases": [],
|
||||
@@ -16518,6 +16623,198 @@ export const ACTIONS: CatalogAction[] = [
|
||||
},
|
||||
"category": "群管理"
|
||||
},
|
||||
{
|
||||
"name": "set_group_admin_permissions",
|
||||
"aliases": [],
|
||||
"summary": "设置指定管理员的撤回和移除成员权限",
|
||||
"returnsSchema": {
|
||||
"type": "null",
|
||||
"description": "服务器确认请求后 data 为 null;不代表已经过客户端回读验证。可用 get_group_admin_permissions 查询。"
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"summary": "允许管理员每日移除至多 10 人",
|
||||
"params": {
|
||||
"group_id": 20001,
|
||||
"user_id": 10001,
|
||||
"kick_member": true,
|
||||
"kick_member_per_day": 10
|
||||
},
|
||||
"notes": "需要当前账号具有修改权限;不会授予管理员角色。仅修改显式字段。开启移除必须提供上限,0 表示不限;修改上限需同时传 kick_member=true。"
|
||||
}
|
||||
],
|
||||
"readOnly": false,
|
||||
"params": [
|
||||
{
|
||||
"name": "group_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "group_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "群号"
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "member_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "QQ 号"
|
||||
},
|
||||
{
|
||||
"name": "recall_member_message",
|
||||
"type": "bool",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kick_member",
|
||||
"type": "bool",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kick_member_per_day",
|
||||
"type": "int",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 200
|
||||
}
|
||||
}
|
||||
],
|
||||
"invariants": [
|
||||
"at least one of: recall_member_message, kick_member",
|
||||
"kick_member=true requires kick_member_per_day: 0, 5, 10, 20, 50, 100 or 200",
|
||||
"kick_member_per_day requires kick_member=true"
|
||||
],
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "群号",
|
||||
"x-role": "group_id"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "QQ 号",
|
||||
"x-role": "member_id"
|
||||
},
|
||||
"recall_member_message": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"kick_member": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"kick_member_per_day": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 200
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"group_id",
|
||||
"user_id"
|
||||
],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"category": "群管理"
|
||||
},
|
||||
{
|
||||
"name": "set_group_admin_receive_verify",
|
||||
"aliases": [],
|
||||
"summary": "设置指定管理员是否接收加群验证消息",
|
||||
"returnsSchema": {
|
||||
"type": "null",
|
||||
"description": "服务器响应确认目标群和管理员后 data 为 null;未确认目标时返回错误。"
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"summary": "开启接收验证消息",
|
||||
"params": {
|
||||
"group_id": 20001,
|
||||
"user_id": 10001,
|
||||
"enable": true
|
||||
},
|
||||
"notes": "user_id 为目标管理员 QQ 号;需要当前账号具有修改权限。独立于撤回和移除成员权限。"
|
||||
}
|
||||
],
|
||||
"readOnly": false,
|
||||
"params": [
|
||||
{
|
||||
"name": "group_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "group_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "群号"
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "uint",
|
||||
"required": true,
|
||||
"role": "member_id",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"desc": "QQ 号"
|
||||
},
|
||||
{
|
||||
"name": "enable",
|
||||
"type": "bool",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
],
|
||||
"invariants": [],
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "群号",
|
||||
"x-role": "group_id"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "QQ 号",
|
||||
"x-role": "member_id"
|
||||
},
|
||||
"enable": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"group_id",
|
||||
"user_id",
|
||||
"enable"
|
||||
],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"category": "群管理"
|
||||
},
|
||||
{
|
||||
"name": "set_group_album_media_like",
|
||||
"aliases": [],
|
||||
@@ -20432,7 +20729,7 @@ export const CATEGORIES: CatalogCategory[] = [
|
||||
},
|
||||
{
|
||||
"category": "群管理",
|
||||
"count": 21
|
||||
"count": 24
|
||||
},
|
||||
{
|
||||
"category": "群文件",
|
||||
|
||||
@@ -466,6 +466,120 @@ export const actions = [
|
||||
},
|
||||
}),
|
||||
|
||||
groupUserAction({
|
||||
name: 'get_group_admin_permissions',
|
||||
summary: '读取指定管理员的撤回、移除成员及每日移除上限',
|
||||
readOnly: true,
|
||||
examples: [
|
||||
{
|
||||
summary: '读取管理员权限',
|
||||
params: { group_id: 20001, user_id: 10001 },
|
||||
notes: 'user_id 为目标管理员 QQ 号;不包含接收验证消息开关。',
|
||||
},
|
||||
],
|
||||
returns:
|
||||
'服务器返回的管理员权限;未返回或未指定的开关为 null。每日上限仅在移除权限开启时返回,0 表示不限。',
|
||||
returnsSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
group_id: { type: 'integer' },
|
||||
user_id: { type: 'integer' },
|
||||
recall_member_message: {
|
||||
type: ['boolean', 'null'],
|
||||
description: '撤回成员消息;null 表示服务器未指定',
|
||||
},
|
||||
kick_member: {
|
||||
type: ['boolean', 'null'],
|
||||
description: '移除群成员;null 表示服务器未指定',
|
||||
},
|
||||
kick_member_per_day: {
|
||||
type: ['integer', 'null'],
|
||||
description: '每日可移除人数,0 不限;权限关闭或未指定时为 null',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'group_id',
|
||||
'user_id',
|
||||
'recall_member_message',
|
||||
'kick_member',
|
||||
'kick_member_per_day',
|
||||
],
|
||||
additionalProperties: false,
|
||||
},
|
||||
run: async (p, ctx) =>
|
||||
okResponse(await ctx.bridge.apis.groupAdmin.getAdminPermissions(p.group_id, p.user_id)),
|
||||
}),
|
||||
|
||||
groupUserAction({
|
||||
name: 'set_group_admin_permissions',
|
||||
summary: '设置指定管理员的撤回和移除成员权限',
|
||||
examples: [
|
||||
{
|
||||
summary: '允许管理员每日移除至多 10 人',
|
||||
params: {
|
||||
group_id: 20001,
|
||||
user_id: 10001,
|
||||
kick_member: true,
|
||||
kick_member_per_day: 10,
|
||||
},
|
||||
notes: '需要当前账号具有修改权限;不会授予管理员角色。仅修改显式字段。开启移除必须提供上限,0 表示不限;修改上限需同时传 kick_member=true。',
|
||||
},
|
||||
],
|
||||
returnsSchema: {
|
||||
type: 'null',
|
||||
description:
|
||||
'服务器确认请求后 data 为 null;不代表已经过客户端回读验证。可用 get_group_admin_permissions 查询。',
|
||||
},
|
||||
params: {
|
||||
recall_member_message: f.bool().optional(),
|
||||
kick_member: f.bool().optional(),
|
||||
kick_member_per_day: f.int({ min: 0, max: 200 }).optional(),
|
||||
},
|
||||
rules: (r) => [
|
||||
r.atLeastOneOf('recall_member_message', 'kick_member'),
|
||||
r.rule(
|
||||
'kick_member=true requires kick_member_per_day: 0, 5, 10, 20, 50, 100 or 200',
|
||||
(p) =>
|
||||
p.kick_member !== true ||
|
||||
(p.kick_member_per_day !== undefined &&
|
||||
[0, 5, 10, 20, 50, 100, 200].includes(p.kick_member_per_day)),
|
||||
),
|
||||
r.rule(
|
||||
'kick_member_per_day requires kick_member=true',
|
||||
(p) => p.kick_member_per_day === undefined || p.kick_member === true,
|
||||
),
|
||||
],
|
||||
run: async (p, ctx) => {
|
||||
await ctx.bridge.apis.groupAdmin.setAdminPermissions(p.group_id, p.user_id, {
|
||||
recallMemberMessage: p.recall_member_message,
|
||||
kickMember: p.kick_member,
|
||||
kickMemberPerDay: p.kick_member_per_day,
|
||||
});
|
||||
return okResponse();
|
||||
},
|
||||
}),
|
||||
|
||||
groupUserAction({
|
||||
name: 'set_group_admin_receive_verify',
|
||||
summary: '设置指定管理员是否接收加群验证消息',
|
||||
examples: [
|
||||
{
|
||||
summary: '开启接收验证消息',
|
||||
params: { group_id: 20001, user_id: 10001, enable: true },
|
||||
notes: 'user_id 为目标管理员 QQ 号;需要当前账号具有修改权限。独立于撤回和移除成员权限。',
|
||||
},
|
||||
],
|
||||
returnsSchema: {
|
||||
type: 'null',
|
||||
description: '服务器响应确认目标群和管理员后 data 为 null;未确认目标时返回错误。',
|
||||
},
|
||||
params: { enable: f.bool() },
|
||||
run: async (p, ctx) => {
|
||||
await ctx.bridge.apis.groupAdmin.setAdminReceiveVerify(p.group_id, p.user_id, p.enable);
|
||||
return okResponse();
|
||||
},
|
||||
}),
|
||||
|
||||
groupUserAction({
|
||||
name: 'set_group_card',
|
||||
examples: [
|
||||
|
||||
@@ -48,6 +48,9 @@ const getGroupTags = requireAction('get_group_tags');
|
||||
const addGroupTag = requireAction('add_group_tag');
|
||||
const deleteGroupTag = requireAction('delete_group_tag');
|
||||
const setGroupAdmin = requireAction('set_group_admin');
|
||||
const getAdminPermissions = requireAction('get_group_admin_permissions');
|
||||
const setAdminPermissions = requireAction('set_group_admin_permissions');
|
||||
const setAdminReceiveVerify = requireAction('set_group_admin_receive_verify');
|
||||
const setGroupCard = requireAction('set_group_card');
|
||||
const setGroupName = requireAction('set_group_name');
|
||||
const setGroupLeave = requireAction('set_group_leave');
|
||||
@@ -73,6 +76,9 @@ describe('group admin actions catalog', () => {
|
||||
['add_group_tag'],
|
||||
['delete_group_tag'],
|
||||
['set_group_admin'],
|
||||
['get_group_admin_permissions'],
|
||||
['set_group_admin_permissions'],
|
||||
['set_group_admin_receive_verify'],
|
||||
['set_group_card'],
|
||||
['set_group_name'],
|
||||
['set_group_leave'],
|
||||
@@ -103,6 +109,9 @@ describe('group admin actions catalog', () => {
|
||||
'normal',
|
||||
'normal',
|
||||
'normal',
|
||||
'normal',
|
||||
'normal',
|
||||
'normal',
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -983,6 +992,96 @@ describe('set_group_member_permissions describe', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('per-administrator permissions', () => {
|
||||
const target = { group_id: 12345, user_id: 67890 };
|
||||
|
||||
it.each([
|
||||
{},
|
||||
{ kick_member_per_day: 20 },
|
||||
{ kick_member: true },
|
||||
{ kick_member: false, kick_member_per_day: 20 },
|
||||
{ kick_member: true, kick_member_per_day: 1 },
|
||||
{ kick_member: true, kick_member_per_day: 201 },
|
||||
])('rejects an ambiguous or invalid patch before effects: %j', async (patch) => {
|
||||
const set = vi.fn();
|
||||
const { ctx } = adminCtx({ setAdminPermissions: set });
|
||||
expect(setAdminPermissions.parse({ ...target, ...patch }).ok).toBe(false);
|
||||
await expect(
|
||||
setAdminPermissions.toHandler(ctx)({ ...target, ...patch }),
|
||||
).resolves.toMatchObject({ status: 'failed' });
|
||||
expect(set).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each([0, 5, 10, 20, 50, 100, 200])(
|
||||
'accepts a supported explicit daily limit %s',
|
||||
(limit) => {
|
||||
expect(
|
||||
setAdminPermissions.parse({
|
||||
...target,
|
||||
kick_member: 'yes',
|
||||
kick_member_per_day: String(limit),
|
||||
}),
|
||||
).toMatchObject({
|
||||
ok: true,
|
||||
value: { ...target, kick_member: true, kick_member_per_day: limit },
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it('forwards false and preserves omitted permissions without promoting the member', async () => {
|
||||
const set = vi.fn(async () => {});
|
||||
const promote = vi.fn();
|
||||
const { ctx } = adminCtx({ setAdminPermissions: set, setAdmin: promote });
|
||||
await expect(
|
||||
setAdminPermissions.toHandler(ctx)({ ...target, recall_member_message: 'no' }),
|
||||
).resolves.toEqual({ status: 'ok', retcode: 0, data: null });
|
||||
expect(set).toHaveBeenCalledExactlyOnceWith(12345, 67890, {
|
||||
recallMemberMessage: false,
|
||||
kickMember: undefined,
|
||||
kickMemberPerDay: undefined,
|
||||
});
|
||||
expect(promote).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('requires an explicit receive-verification switch and forwards false', async () => {
|
||||
expect(setAdminReceiveVerify.parse(target)).toMatchObject({ ok: false, field: 'enable' });
|
||||
const set = vi.fn(async () => {});
|
||||
const { ctx } = adminCtx({ setAdminReceiveVerify: set });
|
||||
await expect(
|
||||
setAdminReceiveVerify.toHandler(ctx)({ ...target, enable: 'off' }),
|
||||
).resolves.toEqual({ status: 'ok', retcode: 0, data: null });
|
||||
expect(set).toHaveBeenCalledExactlyOnceWith(12345, 67890, false);
|
||||
});
|
||||
|
||||
it('returns nullable permissions without defaulting them to true', async () => {
|
||||
const snapshot = {
|
||||
...target,
|
||||
recall_member_message: null,
|
||||
kick_member: true,
|
||||
kick_member_per_day: 0,
|
||||
};
|
||||
const get = vi.fn(async () => snapshot);
|
||||
const { ctx } = adminCtx({ getAdminPermissions: get });
|
||||
await expect(getAdminPermissions.toHandler(ctx)(target)).resolves.toEqual({
|
||||
status: 'ok',
|
||||
retcode: 0,
|
||||
data: snapshot,
|
||||
});
|
||||
expect(get).toHaveBeenCalledExactlyOnceWith(12345, 67890);
|
||||
expect(getAdminPermissions.describe().readOnly).toBe(true);
|
||||
});
|
||||
|
||||
it('propagates a rejected or unconfirmed update', async () => {
|
||||
const set = vi.fn(async () => {
|
||||
throw new Error('target not confirmed');
|
||||
});
|
||||
const { ctx } = adminCtx({ setAdminReceiveVerify: set });
|
||||
await expect(
|
||||
setAdminReceiveVerify.toHandler(ctx)({ ...target, enable: true }),
|
||||
).rejects.toThrow('target not confirmed');
|
||||
});
|
||||
});
|
||||
|
||||
describe('set_group_admin parse', () => {
|
||||
it('defaults enable to true', () => {
|
||||
expect(setGroupAdmin.parse({ group_id: 314159, user_id: 271828 })).toEqual({
|
||||
|
||||
@@ -227,6 +227,43 @@ if (feed) {
|
||||
|
||||
列表续页必须原样传回 `next_cursor`,根据 `has_more` 判断结束,不能因本页不足 10 条而停止。详情中的首批评论位于 `feed.feed.cell_comment.comments`;后续评论使用详情或上一评论页的 `attach_info` 作为 `cursor`。读取回复时,首次可省略 `cursor` 使用完整评论自带的 `reply_attach_info`,之后传上一回复页的 `reply_attach_info`。这些游标各有用途,列表游标还绑定当前账号。登录或访问权限失败会抛出 `SnowLumaApiError`。
|
||||
|
||||
### 单个管理员权限
|
||||
|
||||
`set_group_admin` 用于授予或取消管理员身份。对已有管理员,可通过以下动作读取或修改权限;调用账号需要具有 QQ 服务端要求的管理权限。
|
||||
|
||||
| 动作 | 参数与结果 |
|
||||
| --- | --- |
|
||||
| `get_group_admin_permissions` | `group_id`、`user_id`;返回撤回权限、移除权限和每日移除上限 |
|
||||
| `set_group_admin_permissions` | `group_id`、`user_id`,以及至少一个 `recall_member_message` / `kick_member` |
|
||||
| `set_group_admin_receive_verify` | `group_id`、`user_id`、必填 `enable`;独立设置接收加群验证消息 |
|
||||
|
||||
```ts
|
||||
await bot.raw('set_group_admin_permissions', {
|
||||
group_id: 123456,
|
||||
user_id: 10001,
|
||||
recall_member_message: false,
|
||||
kick_member: true,
|
||||
kick_member_per_day: 20,
|
||||
});
|
||||
|
||||
const permissions = await bot.raw('get_group_admin_permissions', {
|
||||
group_id: 123456,
|
||||
user_id: 10001,
|
||||
});
|
||||
|
||||
await bot.raw('set_group_admin_receive_verify', {
|
||||
group_id: 123456,
|
||||
user_id: 10001,
|
||||
enable: false,
|
||||
});
|
||||
```
|
||||
|
||||
只修改显式提供的权限。开启移除权限必须明确提供 `kick_member_per_day`,支持 `0`、`5`、`10`、`20`、`50`、`100`、`200`,其中 `0` 表示不限。修改上限也须同时传 `kick_member: true`;关闭或省略移除权限时不能提供上限。SDK 的 `kick_member` 使用布尔值,以便类型检查约束上限。
|
||||
|
||||
读取结果包含 `group_id`、`user_id`、`recall_member_message`、`kick_member`、`kick_member_per_day`。服务器未指定的开关返回 `null`;移除权限关闭或未指定时,上限也为 `null`。当前读取接口不返回接收验证消息状态。
|
||||
|
||||
两个写动作分别发送一次请求,不自动重试或授予管理员身份。权限写入成功表示服务器确认请求;接收验证消息写入还会核对响应中的群号和成功管理员列表。两者均返回 `null`。完整的客户端显示和实际权限效果仍需真实 QQ 验证,不能以接口成功替代验收。
|
||||
|
||||
## Message Builder
|
||||
|
||||
```ts
|
||||
|
||||
@@ -29,6 +29,9 @@ export const SNOWLUMA_ACTIONS = [
|
||||
'set_group_add_option',
|
||||
'set_group_search',
|
||||
'set_group_admin',
|
||||
'get_group_admin_permissions',
|
||||
'set_group_admin_permissions',
|
||||
'set_group_admin_receive_verify',
|
||||
'set_group_card',
|
||||
'set_group_name',
|
||||
'set_group_leave',
|
||||
|
||||
@@ -53,6 +53,9 @@ import type {
|
||||
SetGroupAddRequestParams,
|
||||
SetGroupAddOptionParams,
|
||||
SetGroupAdminParams,
|
||||
GroupAdminTargetParams,
|
||||
SetGroupAdminPermissionsParams,
|
||||
SetGroupAdminReceiveVerifyParams,
|
||||
SetGroupBanParams,
|
||||
SetGroupCardParams,
|
||||
SetGroupKickParams,
|
||||
@@ -145,6 +148,7 @@ import type {
|
||||
FriendCategoryResult,
|
||||
FriendMessageHistory,
|
||||
GroupAdminSettings,
|
||||
GroupAdminPermissions,
|
||||
GroupCategoryTagList,
|
||||
GroupAtAllRemainInfo,
|
||||
GroupFileSystemInfo,
|
||||
@@ -242,6 +246,9 @@ export interface SnowLumaActionMap {
|
||||
add_group_tag: { params: GroupCategoryTagNameParams; data: EmptyData };
|
||||
delete_group_tag: { params: GroupCategoryTagNameParams; data: EmptyData };
|
||||
set_group_admin: { params: SetGroupAdminParams; data: EmptyData };
|
||||
get_group_admin_permissions: { params: GroupAdminTargetParams; data: GroupAdminPermissions };
|
||||
set_group_admin_permissions: { params: SetGroupAdminPermissionsParams; data: EmptyData };
|
||||
set_group_admin_receive_verify: { params: SetGroupAdminReceiveVerifyParams; data: EmptyData };
|
||||
set_group_card: { params: SetGroupCardParams; data: EmptyData };
|
||||
set_group_name: { params: SetGroupNameParams; data: EmptyData };
|
||||
set_group_leave: { params: GroupIdParams; data: EmptyData };
|
||||
|
||||
@@ -508,6 +508,36 @@ export interface SetGroupNewMemberHistoryVisibilityParams extends ActionGroupIdP
|
||||
visible: ActionBooleanInput;
|
||||
}
|
||||
|
||||
export interface GroupAdminTargetParams extends ActionGroupIdParams {
|
||||
user_id: ActionNumberInput;
|
||||
}
|
||||
|
||||
export type GroupAdminKickLimit = 0 | 5 | 10 | 20 | 50 | 100 | 200;
|
||||
|
||||
/** Only supplied permissions change. Enabling removal requires an explicit limit. */
|
||||
export type SetGroupAdminPermissionsParams = GroupAdminTargetParams &
|
||||
(
|
||||
| {
|
||||
recall_member_message: ActionBooleanInput;
|
||||
kick_member?: never;
|
||||
kick_member_per_day?: never;
|
||||
}
|
||||
| {
|
||||
recall_member_message?: ActionBooleanInput;
|
||||
kick_member: false;
|
||||
kick_member_per_day?: never;
|
||||
}
|
||||
| {
|
||||
recall_member_message?: ActionBooleanInput;
|
||||
kick_member: true;
|
||||
kick_member_per_day: GroupAdminKickLimit | `${GroupAdminKickLimit}`;
|
||||
}
|
||||
);
|
||||
|
||||
export interface SetGroupAdminReceiveVerifyParams extends GroupAdminTargetParams {
|
||||
enable: ActionBooleanInput;
|
||||
}
|
||||
|
||||
export type SetGroupMemberPermissionsParams = ActionGroupIdParams &
|
||||
(
|
||||
| {
|
||||
|
||||
@@ -270,6 +270,16 @@ export type GroupAdminSettings = {
|
||||
no_code_finger_open: number;
|
||||
};
|
||||
|
||||
export interface GroupAdminPermissions {
|
||||
group_id: number;
|
||||
user_id: number;
|
||||
/** Null means the server did not specify this permission. */
|
||||
recall_member_message: boolean | null;
|
||||
kick_member: boolean | null;
|
||||
/** Zero means unlimited; null means removal is disabled or unspecified. */
|
||||
kick_member_per_day: number | null;
|
||||
}
|
||||
|
||||
export interface GroupTodoListItem {
|
||||
message_id: number;
|
||||
message_seq: number;
|
||||
|
||||
+21
@@ -30,6 +30,15 @@ const qzonePublicReply = {
|
||||
// The same examples are compiled against the published declarations and parsed
|
||||
// by the real server action definitions. They never invoke QQ or perform I/O.
|
||||
export const actionParams = {
|
||||
get_group_admin_permissions: { group_id: '10001', user_id: '10002' },
|
||||
set_group_admin_permissions: {
|
||||
group_id: '10001',
|
||||
user_id: '10002',
|
||||
recall_member_message: false,
|
||||
kick_member: true,
|
||||
kick_member_per_day: '20',
|
||||
},
|
||||
set_group_admin_receive_verify: { group_id: '10001', user_id: '10002', enable: 'on' },
|
||||
_get_friend_dress: { user_id: '10002' },
|
||||
add_custom_face: { file: 'file:///fixture.png' },
|
||||
cancel_group_album_media_like: mediaLike,
|
||||
@@ -180,6 +189,9 @@ export const actionParams = {
|
||||
// Keep this independent of SnowLumaActionMap: a missing map entry must fail the
|
||||
// consumer's coverage check rather than silently remove that example.
|
||||
export type CoveredAction =
|
||||
| 'get_group_admin_permissions'
|
||||
| 'set_group_admin_permissions'
|
||||
| 'set_group_admin_receive_verify'
|
||||
| '_get_friend_dress'
|
||||
| 'add_custom_face'
|
||||
| 'cancel_group_album_media_like'
|
||||
@@ -268,6 +280,15 @@ const flashInfo = {
|
||||
};
|
||||
|
||||
export const actionResults = {
|
||||
get_group_admin_permissions: {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
recall_member_message: null,
|
||||
kick_member: true,
|
||||
kick_member_per_day: 20,
|
||||
},
|
||||
set_group_admin_permissions: null,
|
||||
set_group_admin_receive_verify: null,
|
||||
_get_friend_dress: {
|
||||
target_uin: '10002',
|
||||
is_svip: true,
|
||||
|
||||
+48
@@ -43,6 +43,54 @@ export type QuickAlias = AssertTrue<
|
||||
declare const http: SnowLumaHttpClient;
|
||||
declare const ws: SnowLumaWebSocketClient;
|
||||
|
||||
const adminPermissions = await http.raw('get_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
});
|
||||
export const adminRecall: boolean | null = adminPermissions.recall_member_message;
|
||||
export const adminKickLimit: number | null = adminPermissions.kick_member_per_day;
|
||||
await http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
recall_member_message: false,
|
||||
});
|
||||
await http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
kick_member: false,
|
||||
});
|
||||
await http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
kick_member: true,
|
||||
kick_member_per_day: 0,
|
||||
});
|
||||
await http.raw('set_group_admin_receive_verify', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
enable: false,
|
||||
});
|
||||
// @ts-expect-error a patch must change a permission
|
||||
http.raw('set_group_admin_permissions', { group_id: 10001, user_id: 10002 });
|
||||
// @ts-expect-error enabling removal requires an explicit limit
|
||||
http.raw('set_group_admin_permissions', { group_id: 10001, user_id: 10002, kick_member: true });
|
||||
http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
kick_member: false,
|
||||
// @ts-expect-error a limit without enabling removal is invalid
|
||||
kick_member_per_day: 20,
|
||||
});
|
||||
http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
kick_member: true,
|
||||
// @ts-expect-error only supported limits may be written
|
||||
kick_member_per_day: 1,
|
||||
});
|
||||
// @ts-expect-error receive-verification enable is required
|
||||
http.raw('set_group_admin_receive_verify', { group_id: 10001, user_id: 10002 });
|
||||
|
||||
export const uploadedFile: Promise<UploadFileStreamComplete> = http.uploadFileStream(
|
||||
new Blob(['file']),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user