diff --git a/README.md b/README.md index 97b7b40..9d5ddde 100644 --- a/README.md +++ b/README.md @@ -381,10 +381,20 @@ |348|福萝卜| ### 输出 -你的响应,可以为空(不回应)至多个,以换行分隔,每个格式如下: -```json +你的响应,格式如下,不要用任何代码块包裹,一次只能发送一个: + {"action":"api_name","params":{"a":123,"b":"456"}} -``` + +调用完成后,你可能会收到 API 的响应结果,格式如下: + +{"status":"failed","data":null,"message":1404,"wording":"fail reason"} + 你可以调用的全部 API 如下表。注意:即使之前的记录显示你曾调用过某 API,但如果现在列表中不存在此 API,你就不能调用。 -%v \ No newline at end of file +%v + +根据调用结果,决定你接下来的操作: +- 如果任务成功完成,返回空; +- 如果根据响应你还要进一步操作,首先将你要执行的任务解释给用户(私聊或群聊),消息送达后再执行你的操作; + +用户可以在任何时候终止你的任务或添加新的指示。 \ No newline at end of file diff --git a/actions.yaml b/actions.yaml index 6644c87..b9443d2 100644 --- a/actions.yaml +++ b/actions.yaml @@ -2,45 +2,91 @@ actions: send_private_msg: desc: 发送私聊消息 params: user_id 对方QQ号;message 要发送的内容 (json.RawMessage) + data: message_id 消息ID (number) send_group_msg: desc: 发送群消息 params: group_id 群号;message 要发送的内容 (json.RawMessage) + data: message_id 消息ID (number) delete_msg: desc: 撤回消息 params: message_id 消息ID + data: "-" send_like: desc: 发送好友赞 params: user_id 对方QQ号;times 赞的次数,每个好友每天最多10次 (number) + data: "-" set_group_kick: desc: 群组踢人 params: group_id 群号;user_id 要踢的QQ号;reject_add_request 拒绝此人的加群请求 (boolean) + data: "-" set_group_ban: desc: 群组单人禁言 params: group_id 群号;user_id 要禁言的QQ号;duration 禁言时长(秒),0表示取消禁言 + data: "-" set_group_whole_ban: desc: 群组全员禁言 params: group_id 群号;enable 是否禁言 (boolean) + data: "-" set_group_admin: desc: 群组设置管理员 params: group_id 群号;user_id 要设置管理员的QQ号;enable true为设置,false为取消 + data: "-" set_group_card: desc: 设置群名片 params: group_id 群号;user_id 要设置的QQ号;card 群名片内容,不填或空字符串表示删除群名片 + data: "-" set_group_name: desc: 设置群名 params: group_id 群号;group_name 新群名 + data: "-" set_group_leave: desc: 退出群组 params: group_id 群号;is_dismiss 是否解散 (boolean) + data: "-" set_group_special_title: desc: 设置群组专属头衔 params: group_id 群号;user_id 要设置的QQ号;special_title 专属头衔,不填或空字符串表示删除;duration 专属头衔有效期(秒),-1表示永久 + data: "-" set_friend_add_request: desc: 处理加好友请求 params: flag 加好友请求的flag (string);approve 是否同意请求 (boolean);remark 添加后的好友备注(仅同意时有效) + data: "-" set_group_add_request: desc: 处理加群请求/邀请 params: flag 加群请求的flag (string);sub_type/type add或invite 请求类型(需与上报一致);approve 是否同意请求/邀请 (boolean);reason 拒绝理由(仅拒绝时有效) + data: "-" + get_msg: + desc: 获取消息 + params: message_id 消息ID (number) + data: time 发送时间 (number);message_type 消息类型 (string);sender 发送人信息 (*User);message 消息内容 (json.RawMessage) + get_forward_msg: + desc: 获取合并转发消息 + params: id 合并转发ID (string) + data: message 消息内容 (json.RawMessage) + get_stranger_info: + desc: 获取陌生人信息 + params: user_id QQ号 (number);no_cache 是否不使用缓存 (boolean) + data: "User" + get_friend_list: + desc: 获取好友列表 + params: "-" + data: "[]User" + get_group_info: + desc: 获取群信息 + params: group_id 群号 (number);no_cache 是否不使用缓存 (boolean) + data: group_id 群号 (number);group_name 群名称 (string);member_count 成员数 (number);max_member_count 最大成员数 (number) + get_group_list: + desc: 获取群列表 + params: "-" + data: "[]群信息" + get_group_member_info: + desc: 获取群成员信息 + params: group_id 群号 (number);user_id QQ号 (number);no_cache 是否不使用缓存 (boolean) + data: "User" + get_group_member_list: + desc: 获取群成员列表 + params: group_id 群号 (number) + data: "[]User" config: owner: - send_private_msg @@ -57,7 +103,15 @@ config: - set_group_special_title - set_friend_add_request - set_group_add_request - admin: + - get_msg + - get_forward_msg + - get_stranger_info + - get_friend_list + - get_group_info + - get_group_list + - get_group_member_info + - get_group_member_list + admin: # need to check if gid is the same as admin's gid - send_group_msg - delete_msg - send_like @@ -67,6 +121,18 @@ config: - set_group_card - set_group_name - set_group_special_title - user: + - get_msg + - get_forward_msg + - get_stranger_info + - get_group_info + - get_group_member_info + - get_group_member_list + user: # need to check if gid is the same as user's gid - send_group_msg - send_like + - get_msg + - get_forward_msg + - get_stranger_info + - get_group_info + - get_group_member_info + - get_group_member_list diff --git a/agent.go b/agent.go index b14de58..deab68a 100644 --- a/agent.go +++ b/agent.go @@ -60,6 +60,11 @@ func (ag *Agent) AddRequest(grp int64, req *zero.APIRequest) { ag.log.Add(grp, req, true) } +// AddRequest 添加在执行完 zero.APIRequest 之后得到的响应 +func (ag *Agent) AddResponse(grp int64, resp *APIResponse) { + ag.log.Add(grp, resp, false) +} + // CanViewImage will be true if SetViewImageAPI is called func (ag *Agent) CanViewImage() bool { return ag.hasimageapi @@ -130,6 +135,11 @@ func (ag *Agent) GetAction(api deepinfra.API, p model.Protocol, grp int64, role if err != nil { return } + if strings.HasPrefix(resp, "```") { // AI returns codeblock + _, resp, _ = strings.Cut(resp, "\n") + resp = strings.Trim(resp, "`") + resp = strings.TrimSpace(resp) + } reqs = make([]zero.APIRequest, 0, 2) dec := json.NewDecoder(strings.NewReader(resp)) dec.UseNumber() diff --git a/perm.go b/perm.go index d4d5f2d..3388323 100644 --- a/perm.go +++ b/perm.go @@ -36,6 +36,7 @@ var innerpermtable []byte type PermAction struct { Desc string `yaml:"desc"` Params string `yaml:"params"` + Data string `yaml:"data"` } // Perm 即 actions.yaml 的 Go struct 映射 @@ -51,7 +52,7 @@ func (p *Perm) mdtable(role PermRole) (string, error) { return "", errors.Wrap(ErrNoSuchPermRole, string(role)) } table := strings.Builder{} - table.WriteString("|功能|action|params|\n|---|---|---|") + table.WriteString("|功能|action|params|data|\n|---|---|---|---|") var ac actions if _, ok := p.cache.Load(role); ok { ac = actions{} @@ -71,6 +72,8 @@ func (p *Perm) mdtable(role PermRole) (string, error) { table.WriteByte('|') table.WriteString(a.Params) table.WriteByte('|') + table.WriteString(a.Data) + table.WriteByte('|') } if ac != nil { p.cache.Store(role, ac) diff --git a/perm_test.go b/perm_test.go index d3a6b53..c39f9e5 100644 --- a/perm_test.go +++ b/perm_test.go @@ -2,22 +2,30 @@ package goba import "testing" -const fulltab = `|功能|action|params| -|---|---|---| -|发送私聊消息|send_private_msg|user_id 对方QQ号;message 要发送的内容 (json.RawMessage)| -|发送群消息|send_group_msg|group_id 群号;message 要发送的内容 (json.RawMessage)| -|撤回消息|delete_msg|message_id 消息ID| -|发送好友赞|send_like|user_id 对方QQ号;times 赞的次数,每个好友每天最多10次 (number)| -|群组踢人|set_group_kick|group_id 群号;user_id 要踢的QQ号;reject_add_request 拒绝此人的加群请求 (boolean)| -|群组单人禁言|set_group_ban|group_id 群号;user_id 要禁言的QQ号;duration 禁言时长(秒),0表示取消禁言| -|群组全员禁言|set_group_whole_ban|group_id 群号;enable 是否禁言 (boolean)| -|群组设置管理员|set_group_admin|group_id 群号;user_id 要设置管理员的QQ号;enable true为设置,false为取消| -|设置群名片|set_group_card|group_id 群号;user_id 要设置的QQ号;card 群名片内容,不填或空字符串表示删除群名片| -|设置群名|set_group_name|group_id 群号;group_name 新群名| -|退出群组|set_group_leave|group_id 群号;is_dismiss 是否解散 (boolean)| -|设置群组专属头衔|set_group_special_title|group_id 群号;user_id 要设置的QQ号;special_title 专属头衔,不填或空字符串表示删除;duration 专属头衔有效期(秒),-1表示永久| -|处理加好友请求|set_friend_add_request|flag 加好友请求的flag (string);approve 是否同意请求 (boolean);remark 添加后的好友备注(仅同意时有效)| -|处理加群请求/邀请|set_group_add_request|flag 加群请求的flag (string);sub_type/type add或invite 请求类型(需与上报一致);approve 是否同意请求/邀请 (boolean);reason 拒绝理由(仅拒绝时有效)|` +const fulltab = `|功能|action|params|data| +|---|---|---|---| +|发送私聊消息|send_private_msg|user_id 对方QQ号;message 要发送的内容 (json.RawMessage)|message_id 消息ID (number)| +|发送群消息|send_group_msg|group_id 群号;message 要发送的内容 (json.RawMessage)|message_id 消息ID (number)| +|撤回消息|delete_msg|message_id 消息ID|-| +|发送好友赞|send_like|user_id 对方QQ号;times 赞的次数,每个好友每天最多10次 (number)|-| +|群组踢人|set_group_kick|group_id 群号;user_id 要踢的QQ号;reject_add_request 拒绝此人的加群请求 (boolean)|-| +|群组单人禁言|set_group_ban|group_id 群号;user_id 要禁言的QQ号;duration 禁言时长(秒),0表示取消禁言|-| +|群组全员禁言|set_group_whole_ban|group_id 群号;enable 是否禁言 (boolean)|-| +|群组设置管理员|set_group_admin|group_id 群号;user_id 要设置管理员的QQ号;enable true为设置,false为取消|-| +|设置群名片|set_group_card|group_id 群号;user_id 要设置的QQ号;card 群名片内容,不填或空字符串表示删除群名片|-| +|设置群名|set_group_name|group_id 群号;group_name 新群名|-| +|退出群组|set_group_leave|group_id 群号;is_dismiss 是否解散 (boolean)|-| +|设置群组专属头衔|set_group_special_title|group_id 群号;user_id 要设置的QQ号;special_title 专属头衔,不填或空字符串表示删除;duration 专属头衔有效期(秒),-1表示永久|-| +|处理加好友请求|set_friend_add_request|flag 加好友请求的flag (string);approve 是否同意请求 (boolean);remark 添加后的好友备注(仅同意时有效)|-| +|处理加群请求/邀请|set_group_add_request|flag 加群请求的flag (string);sub_type/type add或invite 请求类型(需与上报一致);approve 是否同意请求/邀请 (boolean);reason 拒绝理由(仅拒绝时有效)|-| +|获取消息|get_msg|message_id 消息ID (number)|time 发送时间 (number);message_type 消息类型 (string);sender 发送人信息 (*User);message 消息内容 (json.RawMessage)| +|获取合并转发消息|get_forward_msg|id 合并转发ID (string)|message 消息内容 (json.RawMessage)| +|获取陌生人信息|get_stranger_info|user_id QQ号 (number);no_cache 是否不使用缓存 (boolean)|User| +|获取好友列表|get_friend_list|-|[]User| +|获取群信息|get_group_info|group_id 群号 (number);no_cache 是否不使用缓存 (boolean)|group_id 群号 (number);group_name 群名称 (string);member_count 成员数 (number);max_member_count 最大成员数 (number)| +|获取群列表|get_group_list|-|[]群信息| +|获取群成员信息|get_group_member_info|group_id 群号 (number);user_id QQ号 (number);no_cache 是否不使用缓存 (boolean)|User| +|获取群成员列表|get_group_member_list|group_id 群号 (number)|[]User|` func TestMDTable(t *testing.T) { ag := new(Agent) diff --git a/public.md b/public.md new file mode 100644 index 0000000..3bbb2f3 --- /dev/null +++ b/public.md @@ -0,0 +1,120 @@ +# 公开 API + +## `get_msg` 获取消息 + +### 参数 + +| 字段名 | 数据类型 | 说明 | +| ------------ | ----- | ------ | +| `message_id` | number (int32) | 消息 ID | + +### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ------------ | ------- | ---------- | +| `time` | number (int32) | 发送时间 | +| `message_type` | string | 消息类型 | +| `sender` | *User | 发送人信息 | +| `message` | json.RawMessage | 消息内容 | + +## `get_forward_msg` 获取合并转发消息 + +### 参数 + +| 字段名 | 数据类型 | 说明 | +| ------------ | ------ | ------ | +| `id` | string | 合并转发 ID | + +### 响应数据 + +| 字段名 | 类型 | 说明 | +| --- | --- | --- | +| `message` | json.RawMessage | 消息内容 | + +## `get_stranger_info` 获取陌生人信息 + +### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `user_id` | number | - | QQ 号 | +| `no_cache` | boolean | `false` | 是否不使用缓存(使用缓存可能更新不及时,但响应更快) | + +### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `user_id` | number (int64) | QQ 号 | +| `nickname` | string | 昵称 | +| `sex` | string | 性别,`male` 或 `female` 或 `unknown` | +| `age` | number (int32) | 年龄 | + +## `get_friend_list` 获取好友列表 + +### 参数 + +无 + +### 响应数据 + +响应内容为 JSON 数组,每个元素如下: + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `user_id` | number (int64) | QQ 号 | +| `nickname` | string | 昵称 | +| `remark` | string | 备注名 | + +## `get_group_info` 获取群信息 + +### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `no_cache` | boolean | `false` | 是否不使用缓存(使用缓存可能更新不及时,但响应更快) | + +### 响应数据 + +| 字段名 | 数据类型 | 说明 | +| ----- | ------- | --- | +| `group_id` | number (int64) | 群号 | +| `group_name` | string | 群名称 | +| `member_count` | number (int32) | 成员数 | +| `max_member_count` | number (int32) | 最大成员数(群容量) | + +## `get_group_list` 获取群列表 + +### 参数 + +无 + +### 响应数据 + +响应内容为 JSON 数组,每个元素和上面的 `get_group_info` 接口相同。 + +## `get_group_member_info` 获取群成员信息 + +### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number | - | 群号 | +| `user_id` | number | - | QQ 号 | +| `no_cache` | boolean | `false` | 是否不使用缓存(使用缓存可能更新不及时,但响应更快) | + +### 响应数据 + +*User + +## `get_group_member_list` 获取群成员列表 + +### 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +| ----- | ------- | ----- | --- | +| `group_id` | number (int64) | - | 群号 | + +### 响应数据 + +响应内容为 JSON 数组,每个元素的内容和上面的 `get_group_member_info` 接口相同。 diff --git a/types.go b/types.go index aa67515..ff8dcf8 100644 --- a/types.go +++ b/types.go @@ -38,3 +38,20 @@ func (ev *Event) String() string { } return strings.TrimSpace(sb.String()) } + +type APIResponse struct { + Status string `json:"status"` + Data json.RawMessage `json:"data"` + Message string `json:"message"` + Wording string `json:"wording"` + RetCode int64 `json:"retcode"` +} + +func (resp *APIResponse) String() string { + sb := strings.Builder{} + err := json.NewEncoder(&sb).Encode(resp) + if err != nil { + panic(errors.Wrap(err, "unexpected")) + } + return strings.TrimSpace(sb.String()) +}