@zhin.js/adapter-qq 1.1.18 → 1.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +21 -18
- package/adapters/qq/index.js +4 -38
- package/adapters/qq/index.ts +3 -46
- package/agents/qq/conversation.js +1 -1
- package/agents/qq/conversation.ts +1 -1
- package/agents/qq/skills/qq/tools/add_role/index.js +2 -1
- package/agents/qq/skills/qq/tools/add_role/index.ts +2 -1
- package/agents/qq/skills/qq/tools/channel_info/index.js +1 -1
- package/agents/qq/skills/qq/tools/channel_info/index.ts +1 -1
- package/agents/qq/skills/qq/tools/create_role/index.js +1 -1
- package/agents/qq/skills/qq/tools/create_role/index.ts +1 -1
- package/agents/qq/skills/qq/tools/guild_kick_member/index.js +1 -1
- package/agents/qq/skills/qq/tools/guild_kick_member/index.ts +1 -1
- package/agents/qq/skills/qq/tools/guild_mute_member/index.js +1 -1
- package/agents/qq/skills/qq/tools/guild_mute_member/index.ts +1 -1
- package/agents/qq/skills/qq/tools/list_channels/index.js +1 -1
- package/agents/qq/skills/qq/tools/list_channels/index.ts +1 -1
- package/agents/qq/skills/qq/tools/list_roles/index.js +1 -1
- package/agents/qq/skills/qq/tools/list_roles/index.ts +1 -1
- package/agents/qq/skills/qq/tools/member_detail/index.js +1 -1
- package/agents/qq/skills/qq/tools/member_detail/index.ts +1 -1
- package/agents/qq/skills/qq/tools/remove_role/index.js +2 -1
- package/agents/qq/skills/qq/tools/remove_role/index.ts +2 -1
- package/agents/qq/skills/qq-conversation/tools/conversation_info/index.js +1 -1
- package/agents/qq/skills/qq-conversation/tools/conversation_info/index.ts +1 -1
- package/agents/qq/skills/qq-directory/tools/list_guilds/index.js +1 -1
- package/agents/qq/skills/qq-directory/tools/list_guilds/index.ts +1 -1
- package/agents/qq/skills/qq-group-admin/tools/group_kick/index.js +2 -2
- package/agents/qq/skills/qq-group-admin/tools/group_kick/index.ts +2 -2
- package/agents/qq/skills/qq-group-admin/tools/handle_join_request/index.js +1 -1
- package/agents/qq/skills/qq-group-admin/tools/handle_join_request/index.ts +1 -1
- package/agents/qq/skills/qq-group-admin/tools/set_mute/index.js +2 -2
- package/agents/qq/skills/qq-group-admin/tools/set_mute/index.ts +2 -2
- package/agents/qq/skills/qq-group-directory/tools/group_info/index.js +1 -1
- package/agents/qq/skills/qq-group-directory/tools/group_info/index.ts +1 -1
- package/agents/qq/skills/qq-group-directory/tools/group_member_info/index.js +1 -1
- package/agents/qq/skills/qq-group-directory/tools/group_member_info/index.ts +1 -1
- package/agents/qq/skills/qq-group-directory/tools/group_members/index.js +1 -1
- package/agents/qq/skills/qq-group-directory/tools/group_members/index.ts +1 -1
- package/agents/qq/skills/qq-group-state/tools/group_blacklist/index.js +1 -1
- package/agents/qq/skills/qq-group-state/tools/group_blacklist/index.ts +1 -1
- package/agents/qq/skills/qq-group-state/tools/list_join_requests/index.js +1 -1
- package/agents/qq/skills/qq-group-state/tools/list_join_requests/index.ts +1 -1
- package/agents/qq/skills/qq-group-state/tools/list_muted/index.js +1 -1
- package/agents/qq/skills/qq-group-state/tools/list_muted/index.ts +1 -1
- package/commands/qq/endpoint/definition.js +41 -36
- package/commands/qq/endpoint/definition.ts +41 -67
- package/lib/adapter.d.ts +13 -0
- package/lib/adapter.js +27 -0
- package/lib/client.d.ts +7 -9
- package/lib/client.js +1 -2
- package/lib/console.d.ts +1 -6
- package/lib/console.js +29 -20
- package/lib/endpoint.d.ts +8 -27
- package/lib/endpoint.js +218 -165
- package/lib/group-admin.d.ts +14 -9
- package/lib/group-admin.js +21 -20
- package/lib/i18n.js +4 -4
- package/lib/image-size.d.ts +6 -1
- package/lib/image-size.js +2 -3
- package/lib/index.d.ts +5 -4
- package/lib/index.js +3 -3
- package/lib/interaction.js +1 -1
- package/lib/outbound.d.ts +4 -1
- package/lib/outbound.js +3 -2
- package/lib/protocol.d.ts +2 -0
- package/lib/qq-console-spec.js +12 -1
- package/lib/qq-console.d.ts +3 -4
- package/lib/qq-console.js +16 -6
- package/lib/qq-endpoint-write.d.ts +6 -10
- package/lib/qq-endpoint-write.js +5 -32
- package/lib/qq-runtime-state.d.ts +11 -10
- package/lib/qq-runtime-state.js +4 -5
- package/lib/qq-send.d.ts +7 -14
- package/lib/qq-send.js +20 -6
- package/lib/webhook.d.ts +3 -6
- package/lib/webhook.js +6 -49
- package/lib/ws.d.ts +10 -33
- package/lib/ws.js +21 -70
- package/middlewares/bot-kind-reply/index.js +1 -2
- package/middlewares/bot-kind-reply/index.ts +0 -2
- package/package.json +19 -19
- package/plugin.js +5 -5
- package/src/adapter.ts +23 -0
- package/src/client.ts +4 -12
- package/src/console.ts +27 -20
- package/src/endpoint.ts +218 -160
- package/src/group-admin.ts +28 -26
- package/src/i18n.ts +4 -4
- package/src/image-size.ts +7 -3
- package/src/index.ts +5 -5
- package/src/interaction.ts +1 -1
- package/src/outbound.ts +3 -2
- package/src/protocol.ts +2 -0
- package/src/qq-console-spec.ts +12 -1
- package/src/qq-console.ts +14 -8
- package/src/qq-endpoint-write.ts +10 -38
- package/src/qq-runtime-state.ts +11 -16
- package/src/qq-send.ts +28 -12
- package/src/webhook.ts +7 -57
- package/src/ws.ts +27 -105
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @zhin.js/adapter-qq
|
|
2
2
|
|
|
3
|
+
## 1.1.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2c3610a: Move account lifecycle ownership into the generic Adapter base and let native Endpoints retain their SDK Client inheritance. Infer platform-specific operation Sessions from a single adapter registry while preserving command parameter, option, configuration and factory inference.
|
|
8
|
+
|
|
9
|
+
Bind message replies, management ports, login challenges and Agent cancellation to the captured account incarnation. Persist runtime account intent with encrypted, revision-checked Host storage; keep account management independent of Root process restarts. Require explicit operator confirmation before importing existing accounts, and give replacement accounts a new identity without inheriting previous Sessions.
|
|
10
|
+
|
|
11
|
+
Expose account save, start, stop, update and replacement through the existing adapter Console, with exact account ownership, truthful pending/unknown outcomes and no startup configuration or environment-file rewrites.
|
|
12
|
+
|
|
13
|
+
Complete the target migration across every adapter, the public authoring API, generators, examples and Console. This intentionally removes the old create factory, inheritable Endpoint/ClientEndpoint classes, Client descriptors and file-rewrite account management; plugin authors must use createAdapter, native Client inheritance and the single AdapterRegistry. Satori and OneBot12 require explicit platform/userId selection, and WeCom requires a separate agentId.
|
|
14
|
+
|
|
15
|
+
Verify opaque credential changes before the same configuration snapshot is committed. Drain admitted native callbacks across close/rollback, cancel target work on stop, and keep raw transport parsing, platform ACK timing and SDK native methods under their existing owners. Account metadata conceals credentials carried in URLs.
|
|
16
|
+
|
|
17
|
+
- a9f4e48: PATCH COMPATIBILITY CUTOVER: this batch intentionally changes plugin APIs. The maintainer explicitly chose patch releases with declared version boundaries. Upgrade the complete tested dependency set; patch numbering does not promise compatibility with the removed interfaces.
|
|
18
|
+
|
|
19
|
+
The first planned floors are zhin.js 1.1.19, Core 1.1.54, Adapter 1.1.26, FeatureKit 1.1.10, Plugin Runtime 1.1.18, Runtime/Isolate 1.1.16 and Agent 1.1.45. Keep old-interface plugins with the earlier locked stack until they are migrated. Adapter's independent Feature API changes from 1.0.0 to 2.0.0; official consumers declare ^2.0.0. Existing Feature API admission rejects explicitly incompatible ranges; omitted API metadata keeps its existing behavior and does not certify compatibility. Runtime engine and patch-only release gates remain unchanged.
|
|
20
|
+
|
|
21
|
+
Use the native-Client Adapter target contract, canonical FeatureKit AdapterRegistry augmentation and named Endpoint control/management requests. Route message controls from canonical message/conversation refs; retain exact source authority and propagate caller/account/explicit-Root-stop cancellation. Replace removed Agent activity feedback exports with source-bound feedback. HMR pause/resume belongs to concrete plugin instances; plugins choose accepted-work policy without changing Controller commit/rollback authority. Cooperative worker/process control cancellation does not kill an isolate or reopen retired business admission.
|
|
22
|
+
|
|
23
|
+
Provide authenticated historical-data preview, exact selected binding, transactional application, authoritative inspection and explicit resumption, including active games. Preserve before-images and journals; never replay an unconfirmed effect, infer an account from an alias, or reuse historical permission grants. Owner V2 approvals remain inactive legacy data, while new writes use V3. Rollback requires matching software, lockfile and verified data; installing old code alone cannot read a new V3 approval file. Conflicting after-images are never overwritten.
|
|
24
|
+
|
|
25
|
+
See docs/plans/adapter-operation-version-boundaries.md and the Chinese/English upgrade guide for the complete version inventory, custom-plugin changes, acceptance and recovery sequence. These code and metadata changes do not authorize merging, publication, deployment, login, production migration or removal of installed workspace patches.
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [2c3610a]
|
|
28
|
+
- Updated dependencies [a9f4e48]
|
|
29
|
+
- Updated dependencies [f8505b0]
|
|
30
|
+
- Updated dependencies [2c3610a]
|
|
31
|
+
- @zhin.js/adapter@1.1.26
|
|
32
|
+
- @zhin.js/feature-kit@1.1.10
|
|
33
|
+
- @zhin.js/core@1.1.54
|
|
34
|
+
- @zhin.js/host-http@1.1.12
|
|
35
|
+
- @zhin.js/client@1.1.22
|
|
36
|
+
- @zhin.js/page@1.1.11
|
|
37
|
+
- @zhin.js/agent-feature@1.1.11
|
|
38
|
+
- @zhin.js/skill@1.1.11
|
|
39
|
+
- @zhin.js/tool@1.1.13
|
|
40
|
+
- @zhin.js/permission@1.1.10
|
|
41
|
+
|
|
3
42
|
## 1.1.18
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Zhin.js QQ 官方机器人适配器(Plugin Runtime),默认通过 **WebSock
|
|
|
14
14
|
- 群管理(官方 v2 群接口):成员列表 / 详情、移出(可拉黑)、禁言(≤30 天)、入群申请审批、黑名单查询;Endpoint 管理端口与自动群审核(`inspectGroupMember` / `moderateGroupMember`)可直接使用
|
|
15
15
|
- 撤回:自己的消息,以及机器人为群管理员时普通成员 2 分钟内的消息(入站原生消息 ID 也可撤回)
|
|
16
16
|
- 频道子频道消息表情回应(`reaction` 操作,Unicode emoji 或 `type:id`)
|
|
17
|
-
- 完整 SDK 业务 API
|
|
17
|
+
- 完整 SDK 业务 API:当前消息操作的 `session.endpoint` 就是 `qq-official-bot` 实例,可直接使用群管理、禁言、自动审批策略、自定义菜单和指令面板等原生 Service
|
|
18
18
|
|
|
19
19
|
## 安装
|
|
20
20
|
|
|
@@ -25,12 +25,13 @@ pnpm add @zhin.js/adapter-qq
|
|
|
25
25
|
## Plugin Runtime
|
|
26
26
|
|
|
27
27
|
- `@zhin.js/adapter` — 约定式 `adapters/qq/index.ts`(`defineAdapter`)
|
|
28
|
-
- `@zhin.js/core` — `
|
|
28
|
+
- `@zhin.js/core` — `endpoint[endpointSpec].events` 入站、`outboundMessageToken` 出站
|
|
29
29
|
- `zhin.js` — `plugin.ts`(`definePlugin`)
|
|
30
30
|
- 配置经插件 `schema.json` 落到顶层 `<instanceKey>`
|
|
31
31
|
- **无需** `@zhin.js/host-http` / `@zhin.js/host-router`(WebSocket 路径)
|
|
32
32
|
|
|
33
|
-
入站:`
|
|
33
|
+
入站:`endpoint[endpointSpec].events.emit('message.receive', { conversation, message, content, sender, metadata })`(ConversationRef 结构化寻址)
|
|
34
|
+
|
|
34
35
|
出站:`send({ conversation, payload })` → `sendPrivateMessage` / `sendGroupMessage` / `sendGuildMessage`
|
|
35
36
|
|
|
36
37
|
## 前置条件
|
|
@@ -70,7 +71,7 @@ WebSocket Identify 的 `intents` **必须与开放平台已开通的权限一致
|
|
|
70
71
|
| `private`(私域) | `GUILD_MESSAGES`(频道全量) | 同上 |
|
|
71
72
|
|
|
72
73
|
公域机器人订阅 `GUILD_MESSAGES` 会 Identify 失败断连。显式配置 `intents` 时优先于 `botKind`。
|
|
73
|
-
`create-zhin` / `zhin setup` 会询问公/私域并写入;`qq endpoint add` 扫码成功后在同一会话追问 `public`/`private`(或
|
|
74
|
+
`create-zhin` / `zhin setup` 会询问公/私域并写入;`qq endpoint add` 扫码成功后在同一会话追问 `public`/`private`(或 `公域`/`私域`),确认后通过所属 Adapter 的单次 CAS 加密保存为未启动账号,需手动启动。
|
|
74
75
|
|
|
75
76
|
多账号:一个插件实例挂多个 endpoint(`endpoints` 数组逐项覆盖顶层字段,`id` 必填):
|
|
76
77
|
|
|
@@ -113,10 +114,10 @@ qq:
|
|
|
113
114
|
|
|
114
115
|
| 命令 | 说明 |
|
|
115
116
|
|------|------|
|
|
116
|
-
| `qq endpoint add [name]` | 手机 QQ 扫码绑定 → **追问公域/私域** →
|
|
117
|
+
| `qq endpoint add [name]` | 手机 QQ 扫码绑定 → **追问公域/私域** → 一次 CAS 保存为未启动账号(无需重启) |
|
|
117
118
|
| `qq endpoint cancel` | 取消进行中的扫码绑定或待确认的公域/私域选择 |
|
|
118
119
|
| `qq endpoint list` | 列出运行中与配置中的 endpoints |
|
|
119
|
-
| `qq endpoint remove <name>` |
|
|
120
|
+
| `qq endpoint remove <name>` | 删除账号配置,取消目标在途并关闭,保留历史 |
|
|
120
121
|
|
|
121
122
|
add/cancel/remove 受 `master` 限制:实例配置声明了 `master`(顶层或 `endpoints[i].master`)时仅
|
|
122
123
|
master 可执行;未配置则放行(首个扫码绑定者会写入该 endpoint 的 `master`)。二维码当前以链接文本下发
|
|
@@ -163,22 +164,20 @@ master 可执行;未配置则放行(首个扫码绑定者会写入该 endpoi
|
|
|
163
164
|
|
|
164
165
|
## 平台 Client 与 QQ API
|
|
165
166
|
|
|
166
|
-
`
|
|
167
|
-
`client.api` 暴露完整的 `qq-official-bot` 1.3 业务 Service 与实体入口;连接启停仍由 Endpoint 生命周期统一管理:
|
|
167
|
+
在已有消息操作中,`session.endpoint` 是完整的 `qq-official-bot` 1.3 原生 Bot 实例,直接暴露业务 Service 与实体入口;账号连接启停仍通过所属 Adapter 管理:
|
|
168
168
|
|
|
169
169
|
```ts
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const client = qqClient.get(context, 'my-qq-bot');
|
|
170
|
+
// session 来自声明 adapter: 'qq' 的当前消息操作。
|
|
171
|
+
const client = session.endpoint;
|
|
173
172
|
|
|
174
|
-
const group = await client.
|
|
175
|
-
const requests = await client.
|
|
176
|
-
await client.
|
|
173
|
+
const group = await client.groupService.getInfo(groupOpenid);
|
|
174
|
+
const requests = await client.groupService.getJoinRequests(groupOpenid);
|
|
175
|
+
await client.groupService.setMemberMute(groupOpenid, [
|
|
177
176
|
{ op: 'add', member_openid: memberOpenid, mute_expire_at: expiresAt },
|
|
178
177
|
]);
|
|
179
178
|
|
|
180
|
-
const menu = await client.
|
|
181
|
-
const panels = await client.
|
|
179
|
+
const menu = await client.menuPanelService.getCustomMenu();
|
|
180
|
+
const panels = await client.menuPanelService.getCommandPanels({ scope: 'group' });
|
|
182
181
|
```
|
|
183
182
|
|
|
184
183
|
群管理接口中有部分是白名单能力,入群审批和禁言还要求机器人具备群管理员权限;
|
|
@@ -224,11 +223,15 @@ QQ 开放平台按有没有带上用户消息的 `msg_id`(或事件的 `event_
|
|
|
224
223
|
启动后打开 Console 的「QQ」页(地址 `/qq`),可以:
|
|
225
224
|
|
|
226
225
|
- 查看运行中的连接、点「测试连接」做连通性诊断;
|
|
227
|
-
-
|
|
228
|
-
- 「平台操作」里扫码绑定新机器人:扫码 → 选择公域 / 私域 →
|
|
226
|
+
- 在账号库查看、修改、启停、替换或删除 QQ 账号;新增走扫码绑定,保存后需手动启动;
|
|
227
|
+
- 「平台操作」里扫码绑定新机器人:扫码 → 选择公域 / 私域 → 通过同一账号 CAS 保存为未启动状态;原来的 `qq endpoint add` 仍然保留。
|
|
229
228
|
|
|
230
229
|
读取需要 `qq:read`,写操作需要 `qq:write`;管理员 full token 不受限。页面里的「扫码绑定新机器人」等价于原来的 `qq endpoint add`。
|
|
231
230
|
|
|
231
|
+
首次修改启动配置里的既有账号前,管理员必须核对清单并确认一次迁移。原 canonical 身份与历史保留,完整账号配置加密进入 Host 数据库;此后账号管理只写数据库,不修改启动文件或 `.env`,不重启进程。没有持久化账号端口的环境可使用静态配置连接,动态写操作明确不可用。
|
|
232
|
+
|
|
233
|
+
启停意图在进程重启后恢复。停止或删除会取消并关闭目标账号的在途操作,其他账号继续运行;删除保留历史。已启动账号的连接配置更新先关闭旧 incarnation,再仅重连该账号;平台身份变化按替换处理,分配新内部身份、保留旧历史,新账号不继承旧 Session、个人设置或启动意图。提交结果未知时先刷新核实,不自动重复 CAS 或平台操作。
|
|
234
|
+
|
|
232
235
|
## 掉线通知
|
|
233
236
|
|
|
234
237
|
QQ 官方机器人掉线 / 启动失败时,可以配置 `notify` 让另一个适配器实例通知 master:
|
package/adapters/qq/index.js
CHANGED
|
@@ -2,12 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Convention entry: discover `adapters/qq/index.ts` → defineAdapter.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { QqHttpEndpoint, QqWebsocketEndpoint } from "../../lib/endpoint.js";
|
|
9
|
-
import { resolveQqConfig, } from "../../lib/protocol.js";
|
|
10
|
-
import { qqRuntimeStateToken } from "../../lib/qq-runtime-state.js";
|
|
5
|
+
import { defineAdapter } from 'zhin.js/adapter';
|
|
6
|
+
import { QqAdapter } from "../../lib/adapter.js";
|
|
7
|
+
import {} from "../../lib/protocol.js";
|
|
11
8
|
export { QqHttpEndpoint, QqWebsocketEndpoint, } from "../../lib/endpoint.js";
|
|
12
9
|
export default defineAdapter({
|
|
13
10
|
capabilities: ['inbound', 'outbound'],
|
|
@@ -20,36 +17,5 @@ export default defineAdapter({
|
|
|
20
17
|
outboundMedia: ['url', 'upload'],
|
|
21
18
|
interactive: 'native',
|
|
22
19
|
},
|
|
23
|
-
|
|
24
|
-
const config = resolveQqConfig(context.config);
|
|
25
|
-
// 注册到插件运行时状态(qq endpoint list 的"运行中"数据源)
|
|
26
|
-
const state = context.use(qqRuntimeStateToken);
|
|
27
|
-
state.endpoints.set(config.id, {
|
|
28
|
-
id: config.id,
|
|
29
|
-
mode: config.mode,
|
|
30
|
-
});
|
|
31
|
-
// 正向判 websocket:TS 对 `mode === 'webhook' || mode === 'middleware'` 的
|
|
32
|
-
// 否定分支不做联合消减(多字面量判别式),反向写会让 config 窄化失败。
|
|
33
|
-
const outbound = context.has?.(outboundHostToken) ? context.use(outboundHostToken) : undefined;
|
|
34
|
-
const notifier = createAdapterOutageNotifier(outbound, config.notify);
|
|
35
|
-
const endpoint = config.mode === 'websocket'
|
|
36
|
-
? new QqWebsocketEndpoint({
|
|
37
|
-
id: context.id,
|
|
38
|
-
config,
|
|
39
|
-
notifier,
|
|
40
|
-
})
|
|
41
|
-
: new QqHttpEndpoint({
|
|
42
|
-
id: context.id,
|
|
43
|
-
http: context.use(httpHostToken),
|
|
44
|
-
config,
|
|
45
|
-
notifier,
|
|
46
|
-
});
|
|
47
|
-
// 运行状态表只增不减:stop 时同步摘除,避免 stop 后 qq endpoint list 仍显示运行中。
|
|
48
|
-
const stopEndpoint = endpoint.stop.bind(endpoint);
|
|
49
|
-
endpoint.stop = async () => {
|
|
50
|
-
state.endpoints.delete(config.id);
|
|
51
|
-
await stopEndpoint();
|
|
52
|
-
};
|
|
53
|
-
return endpoint;
|
|
54
|
-
},
|
|
20
|
+
createAdapter: context => new QqAdapter(context),
|
|
55
21
|
});
|
package/adapters/qq/index.ts
CHANGED
|
@@ -1,35 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Convention entry: discover `adapters/qq/index.ts` → defineAdapter.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { httpHostToken } from '@zhin.js/host-http';
|
|
7
|
-
import { QqHttpEndpoint, QqWebsocketEndpoint } from '../../src/endpoint.js';
|
|
4
|
+
import { defineAdapter } from 'zhin.js/adapter';
|
|
5
|
+
import { QqAdapter } from '../../src/adapter.js';
|
|
8
6
|
import {
|
|
9
|
-
resolveQqConfig,
|
|
10
7
|
type QqEndpointConfig,
|
|
11
8
|
} from '../../src/protocol.js';
|
|
12
|
-
import { qqRuntimeStateToken } from '../../src/qq-runtime-state.js';
|
|
13
9
|
|
|
14
10
|
export {
|
|
15
11
|
QqHttpEndpoint,
|
|
16
12
|
QqWebsocketEndpoint,
|
|
17
13
|
} from '../../src/endpoint.js';
|
|
18
14
|
export type {
|
|
19
|
-
CreateQqBot,
|
|
20
|
-
CreateQqHttpBot,
|
|
21
15
|
QqBotTransport,
|
|
22
16
|
QqEndpointOptions,
|
|
23
17
|
QqHttpBotTransport,
|
|
24
18
|
QqHttpEndpointOptions,
|
|
25
19
|
} from '../../src/endpoint.js';
|
|
26
20
|
|
|
27
|
-
declare module '@zhin.js/core' {
|
|
28
|
-
interface AdapterEndpoints {
|
|
29
|
-
qq: import('../../src/endpoint.js').QqWebsocketEndpoint;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
21
|
export default defineAdapter<QqEndpointConfig>({
|
|
34
22
|
capabilities: ['inbound', 'outbound'],
|
|
35
23
|
operations: ['recall', 'reaction'],
|
|
@@ -41,36 +29,5 @@ export default defineAdapter<QqEndpointConfig>({
|
|
|
41
29
|
outboundMedia: ['url', 'upload'],
|
|
42
30
|
interactive: 'native',
|
|
43
31
|
},
|
|
44
|
-
|
|
45
|
-
const config = resolveQqConfig(context.config);
|
|
46
|
-
// 注册到插件运行时状态(qq endpoint list 的"运行中"数据源)
|
|
47
|
-
const state = context.use(qqRuntimeStateToken);
|
|
48
|
-
state.endpoints.set(config.id, {
|
|
49
|
-
id: config.id,
|
|
50
|
-
mode: config.mode,
|
|
51
|
-
});
|
|
52
|
-
// 正向判 websocket:TS 对 `mode === 'webhook' || mode === 'middleware'` 的
|
|
53
|
-
// 否定分支不做联合消减(多字面量判别式),反向写会让 config 窄化失败。
|
|
54
|
-
const outbound = context.has?.(outboundHostToken) ? context.use(outboundHostToken) : undefined;
|
|
55
|
-
const notifier = createAdapterOutageNotifier(outbound, config.notify);
|
|
56
|
-
const endpoint = config.mode === 'websocket'
|
|
57
|
-
? new QqWebsocketEndpoint({
|
|
58
|
-
id: context.id,
|
|
59
|
-
config,
|
|
60
|
-
notifier,
|
|
61
|
-
})
|
|
62
|
-
: new QqHttpEndpoint({
|
|
63
|
-
id: context.id,
|
|
64
|
-
http: context.use(httpHostToken),
|
|
65
|
-
config,
|
|
66
|
-
notifier,
|
|
67
|
-
});
|
|
68
|
-
// 运行状态表只增不减:stop 时同步摘除,避免 stop 后 qq endpoint list 仍显示运行中。
|
|
69
|
-
const stopEndpoint = endpoint.stop.bind(endpoint);
|
|
70
|
-
endpoint.stop = async () => {
|
|
71
|
-
state.endpoints.delete(config.id);
|
|
72
|
-
await stopEndpoint();
|
|
73
|
-
};
|
|
74
|
-
return endpoint;
|
|
75
|
-
},
|
|
32
|
+
createAdapter: context => new QqAdapter(context),
|
|
76
33
|
});
|
|
@@ -86,7 +86,7 @@ export async function sendToConversation(context, content) {
|
|
|
86
86
|
}
|
|
87
87
|
/** Live check: the bot must be owner/admin of the current group. */
|
|
88
88
|
export async function requireGroupManager(context, groupId) {
|
|
89
|
-
const state = await context.$client.
|
|
89
|
+
const state = await context.$client.groupService.getBotState(groupId);
|
|
90
90
|
context.signal.throwIfAborted();
|
|
91
91
|
return state.member_role === 'owner' || state.member_role === 'admin' ? state : undefined;
|
|
92
92
|
}
|
|
@@ -93,7 +93,7 @@ export async function sendToConversation(context: QqToolContext, content: SendCo
|
|
|
93
93
|
|
|
94
94
|
/** Live check: the bot must be owner/admin of the current group. */
|
|
95
95
|
export async function requireGroupManager(context: QqToolContext, groupId: string) {
|
|
96
|
-
const state = await context.$client.
|
|
96
|
+
const state = await context.$client.groupService.getBotState(groupId);
|
|
97
97
|
context.signal.throwIfAborted();
|
|
98
98
|
return state.member_role === 'owner' || state.member_role === 'admin' ? state : undefined;
|
|
99
99
|
}
|
|
@@ -17,7 +17,8 @@ export default defineAgentTool({
|
|
|
17
17
|
permissions: [platformPermission('qq', 'manage_roles')],
|
|
18
18
|
async execute({ guild_id, channel_id, user_id, role_id }, context) {
|
|
19
19
|
const client = context.$client;
|
|
20
|
-
|
|
20
|
+
await client.memberService.addMemberRole(guild_id, channel_id, user_id, role_id);
|
|
21
|
+
const success = true;
|
|
21
22
|
return { success, message: success ? t(context.locale, 'roleAdded') : t(context.locale, 'operationFailed') };
|
|
22
23
|
},
|
|
23
24
|
});
|
|
@@ -17,7 +17,8 @@ export default defineAgentTool<{ guild_id: string; channel_id: string; user_id:
|
|
|
17
17
|
permissions: [platformPermission('qq', 'manage_roles')],
|
|
18
18
|
async execute({ guild_id, channel_id, user_id, role_id }: { guild_id: string; channel_id: string; user_id: string; role_id: string }, context) {
|
|
19
19
|
const client = context.$client;
|
|
20
|
-
|
|
20
|
+
await client.memberService.addMemberRole(guild_id, channel_id, user_id, role_id);
|
|
21
|
+
const success = true;
|
|
21
22
|
return { success, message: success ? t(context.locale, 'roleAdded') : t(context.locale, 'operationFailed') };
|
|
22
23
|
},
|
|
23
24
|
});
|
|
@@ -13,6 +13,6 @@ export default defineAgentTool({
|
|
|
13
13
|
permissions: [platformPermission('qq', 'guild_admin')],
|
|
14
14
|
async execute({ channel_id }, context) {
|
|
15
15
|
const client = context.$client;
|
|
16
|
-
return client.
|
|
16
|
+
return client.channelService.getInfo(channel_id);
|
|
17
17
|
},
|
|
18
18
|
});
|
|
@@ -13,6 +13,6 @@ export default defineAgentTool<{ channel_id: string }>({
|
|
|
13
13
|
permissions: [platformPermission('qq', 'guild_admin')],
|
|
14
14
|
async execute({ channel_id }: { channel_id: string }, context) {
|
|
15
15
|
const client = context.$client;
|
|
16
|
-
return client.
|
|
16
|
+
return client.channelService.getInfo(channel_id);
|
|
17
17
|
},
|
|
18
18
|
});
|
|
@@ -16,7 +16,7 @@ export default defineAgentTool({
|
|
|
16
16
|
permissions: [platformPermission('qq', 'guild_owner')],
|
|
17
17
|
async execute({ guild_id, name, color }, context) {
|
|
18
18
|
const client = context.$client;
|
|
19
|
-
const role = await client.
|
|
19
|
+
const role = await client.guildService.createRole(guild_id, { name, color: color || 0, hoist: 0 });
|
|
20
20
|
return { success: !!role, role, message: role ? t(context.locale, 'namedRoleCreated', { p0: name }) : t(context.locale, 'createFailed') };
|
|
21
21
|
},
|
|
22
22
|
});
|
|
@@ -16,7 +16,7 @@ export default defineAgentTool<{ guild_id: string; name: string; color?: number
|
|
|
16
16
|
permissions: [platformPermission('qq', 'guild_owner')],
|
|
17
17
|
async execute({ guild_id, name, color }: { guild_id: string; name: string; color?: number }, context) {
|
|
18
18
|
const client = context.$client;
|
|
19
|
-
const role = await client.
|
|
19
|
+
const role = await client.guildService.createRole(guild_id, { name, color: color || 0, hoist: 0 });
|
|
20
20
|
return { success: !!role, role, message: role ? t(context.locale, 'namedRoleCreated', { p0: name }) : t(context.locale, 'createFailed') };
|
|
21
21
|
},
|
|
22
22
|
});
|
|
@@ -22,7 +22,7 @@ export default defineAgentTool({
|
|
|
22
22
|
}),
|
|
23
23
|
async execute({ user_id, blacklist, delete_history_days }, context) {
|
|
24
24
|
const { guildId } = currentGuildChannel(context);
|
|
25
|
-
const ok = await context.$client.
|
|
25
|
+
const ok = await context.$client.memberService.kickMember(guildId, user_id, delete_history_days ?? 0, blacklist === true);
|
|
26
26
|
if (ok === false)
|
|
27
27
|
return { success: false, message: t(context.locale, 'operationFailed') };
|
|
28
28
|
return { success: true, message: t(context.locale, 'memberKicked', { p0: user_id }) };
|
|
@@ -22,7 +22,7 @@ export default defineAgentTool({
|
|
|
22
22
|
}),
|
|
23
23
|
async execute({ user_id, blacklist, delete_history_days }, context) {
|
|
24
24
|
const { guildId } = currentGuildChannel(context);
|
|
25
|
-
const ok = await context.$client.
|
|
25
|
+
const ok = await context.$client.memberService.kickMember(guildId, user_id, delete_history_days ?? 0, blacklist === true);
|
|
26
26
|
if (ok === false) return { success: false, message: t(context.locale, 'operationFailed') };
|
|
27
27
|
return { success: true, message: t(context.locale, 'memberKicked', { p0: user_id }) };
|
|
28
28
|
},
|
|
@@ -19,7 +19,7 @@ export default defineAgentTool({
|
|
|
19
19
|
}),
|
|
20
20
|
async execute({ user_id, duration }, context) {
|
|
21
21
|
const { guildId } = currentGuildChannel(context);
|
|
22
|
-
const members = context.$client.
|
|
22
|
+
const members = context.$client.memberService;
|
|
23
23
|
const seconds = duration ?? 0;
|
|
24
24
|
const ok = seconds === 0
|
|
25
25
|
? await members.unmuteGuildMember(guildId, user_id)
|
|
@@ -19,7 +19,7 @@ export default defineAgentTool({
|
|
|
19
19
|
}),
|
|
20
20
|
async execute({ user_id, duration }, context) {
|
|
21
21
|
const { guildId } = currentGuildChannel(context);
|
|
22
|
-
const members = context.$client.
|
|
22
|
+
const members = context.$client.memberService;
|
|
23
23
|
const seconds = duration ?? 0;
|
|
24
24
|
const ok = seconds === 0
|
|
25
25
|
? await members.unmuteGuildMember(guildId, user_id)
|
|
@@ -13,7 +13,7 @@ export default defineAgentTool({
|
|
|
13
13
|
permissions: [platformPermission('qq', 'manage_channels')],
|
|
14
14
|
async execute({ guild_id }, context) {
|
|
15
15
|
const client = context.$client;
|
|
16
|
-
const channels = await client.
|
|
16
|
+
const channels = await client.channelService.getList(guild_id);
|
|
17
17
|
return { channels, count: channels.length };
|
|
18
18
|
},
|
|
19
19
|
});
|
|
@@ -13,7 +13,7 @@ export default defineAgentTool<{ guild_id: string }>({
|
|
|
13
13
|
permissions: [platformPermission('qq', 'manage_channels')],
|
|
14
14
|
async execute({ guild_id }: { guild_id: string }, context) {
|
|
15
15
|
const client = context.$client;
|
|
16
|
-
const channels = await client.
|
|
16
|
+
const channels = await client.channelService.getList(guild_id);
|
|
17
17
|
return { channels, count: channels.length };
|
|
18
18
|
},
|
|
19
19
|
});
|
|
@@ -13,7 +13,7 @@ export default defineAgentTool({
|
|
|
13
13
|
permissions: [platformPermission('qq', 'manage_roles')],
|
|
14
14
|
async execute({ guild_id }, context) {
|
|
15
15
|
const client = context.$client;
|
|
16
|
-
const roles = await client.
|
|
16
|
+
const roles = await client.guildService.getRoles(guild_id);
|
|
17
17
|
return { roles, count: roles.length };
|
|
18
18
|
},
|
|
19
19
|
});
|
|
@@ -13,7 +13,7 @@ export default defineAgentTool<{ guild_id: string }>({
|
|
|
13
13
|
permissions: [platformPermission('qq', 'manage_roles')],
|
|
14
14
|
async execute({ guild_id }: { guild_id: string }, context) {
|
|
15
15
|
const client = context.$client;
|
|
16
|
-
const roles = await client.
|
|
16
|
+
const roles = await client.guildService.getRoles(guild_id);
|
|
17
17
|
return { roles, count: roles.length };
|
|
18
18
|
},
|
|
19
19
|
});
|
|
@@ -14,6 +14,6 @@ export default defineAgentTool({
|
|
|
14
14
|
permissions: [platformPermission('qq', 'guild_admin')],
|
|
15
15
|
async execute({ guild_id, user_id }, context) {
|
|
16
16
|
const client = context.$client;
|
|
17
|
-
return client.
|
|
17
|
+
return client.memberService.getGuildMemberInfo(guild_id, user_id);
|
|
18
18
|
},
|
|
19
19
|
});
|
|
@@ -14,6 +14,6 @@ export default defineAgentTool<{ guild_id: string; user_id: string }>({
|
|
|
14
14
|
permissions: [platformPermission('qq', 'guild_admin')],
|
|
15
15
|
async execute({ guild_id, user_id }: { guild_id: string; user_id: string }, context) {
|
|
16
16
|
const client = context.$client;
|
|
17
|
-
return client.
|
|
17
|
+
return client.memberService.getGuildMemberInfo(guild_id, user_id);
|
|
18
18
|
},
|
|
19
19
|
});
|
|
@@ -17,7 +17,8 @@ export default defineAgentTool({
|
|
|
17
17
|
permissions: [platformPermission('qq', 'manage_roles')],
|
|
18
18
|
async execute({ guild_id, channel_id, user_id, role_id }, context) {
|
|
19
19
|
const client = context.$client;
|
|
20
|
-
|
|
20
|
+
await client.memberService.removeMemberRole(guild_id, channel_id, user_id, role_id);
|
|
21
|
+
const success = true;
|
|
21
22
|
return { success, message: success ? t(context.locale, 'roleRemoved') : t(context.locale, 'operationFailed') };
|
|
22
23
|
},
|
|
23
24
|
});
|
|
@@ -17,7 +17,8 @@ export default defineAgentTool<{ guild_id: string; channel_id: string; user_id:
|
|
|
17
17
|
permissions: [platformPermission('qq', 'manage_roles')],
|
|
18
18
|
async execute({ guild_id, channel_id, user_id, role_id }: { guild_id: string; channel_id: string; user_id: string; role_id: string }, context) {
|
|
19
19
|
const client = context.$client;
|
|
20
|
-
|
|
20
|
+
await client.memberService.removeMemberRole(guild_id, channel_id, user_id, role_id);
|
|
21
|
+
const success = true;
|
|
21
22
|
return { success, message: success ? t(context.locale, 'roleRemoved') : t(context.locale, 'operationFailed') };
|
|
22
23
|
},
|
|
23
24
|
});
|
|
@@ -38,7 +38,7 @@ export default defineAgentTool({
|
|
|
38
38
|
leaveGroup: false,
|
|
39
39
|
},
|
|
40
40
|
};
|
|
41
|
-
const api = context.$client
|
|
41
|
+
const api = context.$client;
|
|
42
42
|
if (conversation.kind === 'group') {
|
|
43
43
|
const [state, info] = await Promise.all([
|
|
44
44
|
api.groupService.getBotState(conversation.id),
|
|
@@ -36,7 +36,7 @@ export default defineAgentTool({
|
|
|
36
36
|
leaveGroup: false,
|
|
37
37
|
},
|
|
38
38
|
};
|
|
39
|
-
const api = context.$client
|
|
39
|
+
const api = context.$client;
|
|
40
40
|
if (conversation.kind === 'group') {
|
|
41
41
|
const [state, info] = await Promise.all([
|
|
42
42
|
api.groupService.getBotState(conversation.id),
|
|
@@ -8,7 +8,7 @@ export default defineAgentTool({
|
|
|
8
8
|
tags: ['qq'],
|
|
9
9
|
async execute(_input, context) {
|
|
10
10
|
const client = context.$client;
|
|
11
|
-
const guilds = await client.
|
|
11
|
+
const guilds = await client.guildService.getList();
|
|
12
12
|
return { guilds, count: guilds.length };
|
|
13
13
|
},
|
|
14
14
|
});
|
|
@@ -8,7 +8,7 @@ export default defineAgentTool<Record<string, never>>({
|
|
|
8
8
|
tags: ['qq'],
|
|
9
9
|
async execute(_input, context) {
|
|
10
10
|
const client = context.$client;
|
|
11
|
-
const guilds = await client.
|
|
11
|
+
const guilds = await client.guildService.getList();
|
|
12
12
|
return { guilds, count: guilds.length };
|
|
13
13
|
},
|
|
14
14
|
});
|
|
@@ -21,7 +21,7 @@ export default defineAgentTool({
|
|
|
21
21
|
const client = context.$client;
|
|
22
22
|
const [self, member] = await Promise.all([
|
|
23
23
|
requireGroupManager(context, group),
|
|
24
|
-
client.
|
|
24
|
+
client.groupService.getMemberInfo(group, user_id),
|
|
25
25
|
]);
|
|
26
26
|
if (!self)
|
|
27
27
|
return { success: false, message: t(context.locale, 'botNotManager') };
|
|
@@ -29,7 +29,7 @@ export default defineAgentTool({
|
|
|
29
29
|
return { success: false, message: t(context.locale, 'targetNotMember') };
|
|
30
30
|
}
|
|
31
31
|
context.signal.throwIfAborted();
|
|
32
|
-
const { blacklistFailed } = await kickQqGroupMember(client
|
|
32
|
+
const { blacklistFailed } = await kickQqGroupMember(client, { groupId: group, userId: user_id, addToBlacklist: blacklist === true });
|
|
33
33
|
return {
|
|
34
34
|
success: true,
|
|
35
35
|
message: t(context.locale, 'memberKicked', { p0: member.username || user_id }),
|
|
@@ -21,14 +21,14 @@ export default defineAgentTool({
|
|
|
21
21
|
const client = context.$client;
|
|
22
22
|
const [self, member] = await Promise.all([
|
|
23
23
|
requireGroupManager(context, group),
|
|
24
|
-
client.
|
|
24
|
+
client.groupService.getMemberInfo(group, user_id),
|
|
25
25
|
]);
|
|
26
26
|
if (!self) return { success: false, message: t(context.locale, 'botNotManager') };
|
|
27
27
|
if (member.member_openid !== user_id || member.member_role !== 'member' || member.bot || user_id === self.member_openid) {
|
|
28
28
|
return { success: false, message: t(context.locale, 'targetNotMember') };
|
|
29
29
|
}
|
|
30
30
|
context.signal.throwIfAborted();
|
|
31
|
-
const { blacklistFailed } = await kickQqGroupMember(client
|
|
31
|
+
const { blacklistFailed } = await kickQqGroupMember(client, { groupId: group, userId: user_id, addToBlacklist: blacklist === true });
|
|
32
32
|
return {
|
|
33
33
|
success: true,
|
|
34
34
|
message: t(context.locale, 'memberKicked', { p0: member.username || user_id }),
|
|
@@ -22,7 +22,7 @@ export default defineAgentTool({
|
|
|
22
22
|
const group = currentGroup(context);
|
|
23
23
|
if (!await requireGroupManager(context, group))
|
|
24
24
|
return { success: false, message: t(context.locale, 'botNotManager') };
|
|
25
|
-
await context.$client.
|
|
25
|
+
await context.$client.groupService.approveJoinRequest(group, user_id, {
|
|
26
26
|
op: approve ? 'approve' : 'decline',
|
|
27
27
|
...(join_request_id ? { join_request_id } : {}),
|
|
28
28
|
...(!approve && reason ? { reject_reason: reason } : {}),
|
|
@@ -21,7 +21,7 @@ export default defineAgentTool({
|
|
|
21
21
|
async execute({ user_id, join_request_id, approve, reason, blacklist }, context) {
|
|
22
22
|
const group = currentGroup(context);
|
|
23
23
|
if (!await requireGroupManager(context, group)) return { success: false, message: t(context.locale, 'botNotManager') };
|
|
24
|
-
await context.$client.
|
|
24
|
+
await context.$client.groupService.approveJoinRequest(group, user_id, {
|
|
25
25
|
op: approve ? 'approve' : 'decline',
|
|
26
26
|
...(join_request_id ? { join_request_id } : {}),
|
|
27
27
|
...(!approve && reason ? { reject_reason: reason } : {}),
|
|
@@ -21,7 +21,7 @@ export default defineAgentTool({
|
|
|
21
21
|
const seconds = duration ?? 0;
|
|
22
22
|
const [self, member] = await Promise.all([
|
|
23
23
|
requireGroupManager(context, group),
|
|
24
|
-
client.
|
|
24
|
+
client.groupService.getMemberInfo(group, user_id),
|
|
25
25
|
]);
|
|
26
26
|
if (!self)
|
|
27
27
|
return { success: false, message: t(context.locale, 'botNotManager') };
|
|
@@ -30,7 +30,7 @@ export default defineAgentTool({
|
|
|
30
30
|
return { success: false, message: t(context.locale, 'targetNotMember') };
|
|
31
31
|
}
|
|
32
32
|
context.signal.throwIfAborted();
|
|
33
|
-
await muteQqGroupMember(client
|
|
33
|
+
await muteQqGroupMember(client, { groupId: group, userId: user_id, durationSeconds: seconds });
|
|
34
34
|
const user = member.username || user_id;
|
|
35
35
|
return { success: true, message: seconds === 0 ? t(context.locale, 'unmuted', { user }) : t(context.locale, 'muted', { user, seconds }) };
|
|
36
36
|
},
|
|
@@ -21,7 +21,7 @@ export default defineAgentTool({
|
|
|
21
21
|
const seconds = duration ?? 0;
|
|
22
22
|
const [self, member] = await Promise.all([
|
|
23
23
|
requireGroupManager(context, group),
|
|
24
|
-
client.
|
|
24
|
+
client.groupService.getMemberInfo(group, user_id),
|
|
25
25
|
]);
|
|
26
26
|
if (!self) return { success: false, message: t(context.locale, 'botNotManager') };
|
|
27
27
|
// 官方:新增 / 更新禁言只能作用于普通成员;解除不限制。
|
|
@@ -29,7 +29,7 @@ export default defineAgentTool({
|
|
|
29
29
|
return { success: false, message: t(context.locale, 'targetNotMember') };
|
|
30
30
|
}
|
|
31
31
|
context.signal.throwIfAborted();
|
|
32
|
-
await muteQqGroupMember(client
|
|
32
|
+
await muteQqGroupMember(client, { groupId: group, userId: user_id, durationSeconds: seconds });
|
|
33
33
|
const user = member.username || user_id;
|
|
34
34
|
return { success: true, message: seconds === 0 ? t(context.locale, 'unmuted', { user }) : t(context.locale, 'muted', { user, seconds }) };
|
|
35
35
|
},
|
|
@@ -10,7 +10,7 @@ export default defineAgentTool({
|
|
|
10
10
|
readOnly: true,
|
|
11
11
|
inputSchema: z.object({}),
|
|
12
12
|
async execute(_input, context) {
|
|
13
|
-
const info = await context.$client.
|
|
13
|
+
const info = await context.$client.groupService.getInfo(currentGroup(context));
|
|
14
14
|
return { success: true, group: info };
|
|
15
15
|
},
|
|
16
16
|
});
|