@zhin.js/adapter-onebot12 1.0.1 → 1.1.2
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 +940 -0
- package/README.md +61 -69
- package/adapters/onebot12/index.js +50 -0
- package/adapters/onebot12/index.ts +64 -0
- package/commands/onebot12/endpoint/add/[id]/index.js +3 -0
- package/commands/onebot12/endpoint/add/[id]/index.ts +3 -0
- package/commands/onebot12/endpoint/definition.js +26 -0
- package/commands/onebot12/endpoint/definition.ts +24 -0
- package/commands/onebot12/endpoint/list/index.js +3 -0
- package/commands/onebot12/endpoint/list/index.ts +3 -0
- package/commands/onebot12/endpoint/remove/[id]/index.js +3 -0
- package/commands/onebot12/endpoint/remove/[id]/index.ts +3 -0
- package/lib/client.d.ts +20 -0
- package/lib/client.js +33 -0
- package/lib/content-port.d.ts +4 -0
- package/lib/content-port.js +45 -0
- package/lib/endpoint-management.d.ts +16 -0
- package/lib/endpoint-management.js +47 -0
- package/lib/index.d.ts +10 -19
- package/lib/index.js +7 -27
- package/lib/onebot12-runtime-state.d.ts +1 -0
- package/lib/onebot12-runtime-state.js +6 -0
- package/lib/protocol.d.ts +157 -0
- package/lib/protocol.js +431 -0
- package/lib/side-event-dispatch.d.ts +7 -0
- package/lib/side-event-dispatch.js +36 -0
- package/lib/webhook.d.ts +23 -0
- package/lib/webhook.js +157 -0
- package/lib/ws-endpoint.d.ts +22 -0
- package/lib/ws-endpoint.js +219 -0
- package/lib/ws-transport.d.ts +12 -0
- package/lib/ws-transport.js +58 -0
- package/lib/ws-types.d.ts +17 -0
- package/lib/ws-types.js +1 -0
- package/lib/wss-auth.d.ts +2 -0
- package/lib/wss-auth.js +16 -0
- package/lib/wss-endpoint.d.ts +25 -0
- package/lib/wss-endpoint.js +193 -0
- package/package.json +67 -16
- package/plugin.js +14 -0
- package/schema.json +120 -0
- package/src/client.ts +81 -0
- package/src/content-port.ts +49 -0
- package/src/endpoint-management.ts +73 -0
- package/src/index.ts +63 -37
- package/src/onebot12-runtime-state.ts +7 -0
- package/src/protocol.ts +575 -0
- package/src/side-event-dispatch.ts +48 -0
- package/src/webhook.ts +219 -0
- package/src/ws-endpoint.ts +285 -0
- package/src/ws-transport.ts +88 -0
- package/src/ws-types.ts +21 -0
- package/src/wss-auth.ts +17 -0
- package/src/wss-endpoint.ts +248 -0
- package/lib/adapter.d.ts +0 -18
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js +0 -41
- package/lib/adapter.js.map +0 -1
- package/lib/api.d.ts +0 -14
- package/lib/api.d.ts.map +0 -1
- package/lib/api.js +0 -34
- package/lib/api.js.map +0 -1
- package/lib/endpoint-webhook.d.ts +0 -25
- package/lib/endpoint-webhook.d.ts.map +0 -1
- package/lib/endpoint-webhook.js +0 -118
- package/lib/endpoint-webhook.js.map +0 -1
- package/lib/endpoint-ws.d.ts +0 -26
- package/lib/endpoint-ws.d.ts.map +0 -1
- package/lib/endpoint-ws.js +0 -210
- package/lib/endpoint-ws.js.map +0 -1
- package/lib/endpoint-wss.d.ts +0 -26
- package/lib/endpoint-wss.d.ts.map +0 -1
- package/lib/endpoint-wss.js +0 -187
- package/lib/endpoint-wss.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/types.d.ts +0 -77
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -5
- package/lib/types.js.map +0 -1
- package/lib/utils.d.ts +0 -45
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js +0 -60
- package/lib/utils.js.map +0 -1
- package/skills/onebot12/SKILL.md +0 -36
- package/src/adapter.ts +0 -54
- package/src/api.ts +0 -48
- package/src/endpoint-webhook.ts +0 -130
- package/src/endpoint-ws.ts +0 -222
- package/src/endpoint-wss.ts +0 -202
- package/src/types.ts +0 -86
- package/src/utils.ts +0 -87
package/README.md
CHANGED
|
@@ -1,105 +1,97 @@
|
|
|
1
1
|
# @zhin.js/adapter-onebot12
|
|
2
2
|
|
|
3
|
-
Zhin.js [OneBot 12](https://12.onebot.dev/)
|
|
3
|
+
Zhin.js [OneBot 12](https://12.onebot.dev/) 适配器(Plugin Runtime)。默认 **正向 WebSocket 客户端**(`connection: ws`);亦支持 **HTTP Webhook** 与 **反向 WS**(经 `httpHostToken` 注册路由)。
|
|
4
4
|
|
|
5
5
|
## 功能特性
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
- 🔐 `access_token` 鉴权(Bearer)
|
|
13
|
-
- 📨 私聊 / 群聊 / 频道消息收发,消息段与 OneBot 12 标准一致
|
|
7
|
+
- [OneBot 12 标准](https://12.onebot.dev/) 兼容(事件 + 动作)
|
|
8
|
+
- 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
|
|
9
|
+
- **正向 WebSocket**(`connection: ws`):应用连 OneBot 实现的 WS 服务器
|
|
10
|
+
- `access_token` 鉴权(Bearer + query)
|
|
11
|
+
- 入站经 `Endpoint.emit(...)`;出站 `send({ conversation, payload })`
|
|
14
12
|
|
|
15
13
|
## 安装
|
|
16
14
|
|
|
17
15
|
```bash
|
|
18
|
-
pnpm add @zhin.js/adapter-onebot12
|
|
16
|
+
pnpm add @zhin.js/adapter-onebot12
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
## Plugin Runtime
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
- `@zhin.js/adapter` — 约定式 `adapters/onebot12/index.ts`(`defineAdapter`)
|
|
22
|
+
- `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
|
|
23
|
+
- `zhin.js` — `plugin.ts`(`definePlugin`)
|
|
24
|
+
- 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
|
|
25
|
+
|
|
26
|
+
`AdapterIndex` 会把实例默认值与 `endpoints[]` 的逐项覆盖合并;协议层只接收一个已经展开的 endpoint 配置,不再读取嵌套 endpoint 或从进程环境推断身份。Webhook 配置必须同时提供 `path` 与 `api_url`,从而在启动前建立完整的双向能力。
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
入站:`gateway.receive({ conversation: ConversationRef, message: { conversation, id }, content, sender, metadata })`
|
|
29
|
+
出站:`send({ conversation, payload })` → WS `send_message`(payload 已由 gateway/core 渲染;无 segment-mapper)
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
每个 Endpoint 的 `$client` 是 `@imhelper/onebot-v12` 的 `OneBotV12Client`。业务代码直接调用
|
|
32
|
+
`$client.call(action, params)` 和 Client 的公开平台能力;Webhook 使用 Client 的
|
|
33
|
+
`acceptHttp()`,双工 WS 则由 Endpoint 分离 `echo` 响应后把事件交给 `ingest()`。
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
## 前置条件
|
|
36
|
+
|
|
37
|
+
1. 启动兼容 OneBot 12 的实现,并确认其支持所选 WS 或 Webhook 模式。
|
|
38
|
+
2. Webhook 出站还需要可用的 `api_url`;反向连接需要实现端可达 Zhin HTTP Host。
|
|
39
|
+
3. 两端配置相同的 `access_token`,生产环境必须启用鉴权。
|
|
40
|
+
|
|
41
|
+
## 最小配置
|
|
32
42
|
|
|
33
43
|
```yaml
|
|
44
|
+
# zhin.config.yml(Plugin Runtime)
|
|
34
45
|
plugins:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
endpoints:
|
|
38
|
-
- context: onebot12
|
|
46
|
+
onebot12:
|
|
39
47
|
connection: ws
|
|
40
|
-
name: ob12-bot
|
|
41
|
-
url: "ws://127.0.0.1:6700"
|
|
42
|
-
access_token: "${ONEBOT12_ACCESS_TOKEN}"
|
|
43
48
|
reconnect_interval: 5000
|
|
44
49
|
heartbeat_interval: 30000
|
|
50
|
+
endpoints:
|
|
51
|
+
- id: ob12-bot
|
|
52
|
+
url: "ws://127.0.0.1:6700"
|
|
53
|
+
access_token: "${ONEBOT12_ACCESS_TOKEN}"
|
|
45
54
|
```
|
|
46
55
|
|
|
47
|
-
|
|
56
|
+
根插件 `zhin.plugins`(或项目图)需引用 `@zhin.js/adapter-onebot12`(`instanceKey: onebot12`)。
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
## 连接方式
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
connection: webhook
|
|
59
|
-
name: ob12-webhook-bot
|
|
60
|
-
path: "/onebot12/webhook"
|
|
61
|
-
api_url: "http://127.0.0.1:6700" # 可选,用于 send_message / delete_message
|
|
62
|
-
access_token: "${ONEBOT12_ACCESS_TOKEN}"
|
|
63
|
-
```
|
|
60
|
+
| connection | 状态 |
|
|
61
|
+
|------------|------|
|
|
62
|
+
| `ws` | 已实现(推荐) |
|
|
63
|
+
| `webhook` | 已实现:POST 入站 + `api_url` HTTP 出站 |
|
|
64
|
+
| `wss` | 已实现:反向 WS(httpHostToken) |
|
|
65
|
+
|
|
66
|
+
## 鉴权
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
- **Bearer**:`Authorization: Bearer <access_token>`
|
|
69
|
+
- 正向 WS 在 Upgrade 时附带请求头,并在 URL query 写入 `access_token`
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
plugins:
|
|
69
|
-
- "@zhin.js/host-router"
|
|
70
|
-
- "@zhin.js/adapter-onebot12"
|
|
71
|
-
|
|
72
|
-
endpoints:
|
|
73
|
-
- context: onebot12
|
|
74
|
-
connection: wss
|
|
75
|
-
name: ob12-wss-bot
|
|
76
|
-
path: "/onebot12/event"
|
|
77
|
-
access_token: "${ONEBOT12_ACCESS_TOKEN}"
|
|
78
|
-
heartbeat_interval: 30000
|
|
79
|
-
```
|
|
71
|
+
## 动作与事件
|
|
80
72
|
|
|
81
|
-
|
|
73
|
+
- 事件:`type`(meta/message/notice/request)、`detail_type`、`message` 等,见 [事件](https://12.onebot.dev/connect/data-protocol/event/)。
|
|
74
|
+
- 动作:`send_message`、`delete_message`、`get_status` 等,见 [动作请求](https://12.onebot.dev/connect/data-protocol/action-request/)。
|
|
82
75
|
|
|
83
|
-
|
|
84
|
-
- 正向 WS 在建立连接时通过 HTTP Upgrade 头鉴权;Webhook / 反向 WS 同上
|
|
76
|
+
## AI 工具
|
|
85
77
|
|
|
86
|
-
|
|
78
|
+
技能说明见 `skills/onebot12/SKILL.md`。
|
|
87
79
|
|
|
88
|
-
##
|
|
80
|
+
## 文档链接
|
|
89
81
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
| `webhook` | 实现 POST 事件到应用 path;发消息需配置 `api_url` |
|
|
94
|
-
| `wss` | 应用开 WS 服务端,实现连上来 |
|
|
82
|
+
- [OneBot 12 标准](https://12.onebot.dev/)
|
|
83
|
+
- [OneBot Connect WebSocket](https://12.onebot.dev/connect/communication/websocket/)
|
|
84
|
+
- [适配器概览](https://zhin.js.org/essentials/adapters)
|
|
95
85
|
|
|
96
|
-
##
|
|
86
|
+
## 故障排查
|
|
97
87
|
|
|
98
|
-
|
|
99
|
-
|
|
88
|
+
| 现象 | 排查 |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| WS 连接失败 | 核对 OneBot 版本、连接方向、URL 与端口 |
|
|
91
|
+
| Webhook 能收不能发 | 检查 `api_url` 可达性与 `send_message` 支持 |
|
|
92
|
+
| 401 或握手失败 | 确认 Header/query token 与实现端一致 |
|
|
93
|
+
| 事件字段无法识别 | 确认实现端发送的是 OneBot 12 而非 v11 结构 |
|
|
100
94
|
|
|
101
|
-
##
|
|
95
|
+
## 许可证
|
|
102
96
|
|
|
103
|
-
|
|
104
|
-
- [OneBot Connect 通信方式](https://12.onebot.dev/connect/communication/websocket/)
|
|
105
|
-
- [数据协议(事件 / 动作)](https://12.onebot.dev/connect/data-protocol/event/)
|
|
97
|
+
MIT License
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
/**
|
|
3
|
+
* Convention entry: discover `adapters/onebot12/index.ts` → defineAdapter.
|
|
4
|
+
*/
|
|
5
|
+
import { defineAdapter } from 'zhin.js/adapter';
|
|
6
|
+
import { httpHostToken } from '@zhin.js/host-http';
|
|
7
|
+
import { OneBot12WebhookEndpoint } from "../../lib/webhook.js";
|
|
8
|
+
import { OneBot12WsEndpoint } from "../../lib/ws-endpoint.js";
|
|
9
|
+
import { OneBot12WssEndpoint } from "../../lib/wss-endpoint.js";
|
|
10
|
+
import { resolveOneBot12Config, } from "../../lib/protocol.js";
|
|
11
|
+
import { onebot12RuntimeStateToken } from "../../lib/onebot12-runtime-state.js";
|
|
12
|
+
export { OneBot12WebhookEndpoint } from "../../lib/webhook.js";
|
|
13
|
+
export { OneBot12WsEndpoint } from "../../lib/ws-endpoint.js";
|
|
14
|
+
export { OneBot12WssEndpoint } from "../../lib/wss-endpoint.js";
|
|
15
|
+
export default defineAdapter({
|
|
16
|
+
capabilities: ['inbound', 'outbound'],
|
|
17
|
+
operations: ['recall'],
|
|
18
|
+
// 媒体段经 upload_file 物化为 file_id(spec 正式投递);上传失败降级扩展字段透传。
|
|
19
|
+
// 无卡片交互面,交互段降级纯文本。
|
|
20
|
+
segments: {
|
|
21
|
+
outboundMedia: ['url', 'path', 'base64', 'upload'],
|
|
22
|
+
interactive: 'text',
|
|
23
|
+
},
|
|
24
|
+
create(context) {
|
|
25
|
+
const config = resolveOneBot12Config(context.config);
|
|
26
|
+
// 注册到插件运行时状态(onebot12 endpoint list 的"运行中"数据源)
|
|
27
|
+
context.use(onebot12RuntimeStateToken).endpoints.set(config.id, {
|
|
28
|
+
id: config.id,
|
|
29
|
+
mode: config.connection,
|
|
30
|
+
});
|
|
31
|
+
if (config.connection === 'webhook') {
|
|
32
|
+
return new OneBot12WebhookEndpoint({
|
|
33
|
+
id: context.id,
|
|
34
|
+
http: context.use(httpHostToken),
|
|
35
|
+
config,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (config.connection === 'wss') {
|
|
39
|
+
return new OneBot12WssEndpoint({
|
|
40
|
+
id: context.id,
|
|
41
|
+
http: context.use(httpHostToken),
|
|
42
|
+
config,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return new OneBot12WsEndpoint({
|
|
46
|
+
id: context.id,
|
|
47
|
+
config,
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convention entry: discover `adapters/onebot12/index.ts` → defineAdapter.
|
|
3
|
+
*/
|
|
4
|
+
import { defineAdapter } from 'zhin.js/adapter';
|
|
5
|
+
import { httpHostToken } from '@zhin.js/host-http';
|
|
6
|
+
import { OneBot12WebhookEndpoint } from '../../src/webhook.js';
|
|
7
|
+
import { OneBot12WsEndpoint } from '../../src/ws-endpoint.js';
|
|
8
|
+
import { OneBot12WssEndpoint } from '../../src/wss-endpoint.js';
|
|
9
|
+
import {
|
|
10
|
+
resolveOneBot12Config,
|
|
11
|
+
type OneBot12EndpointConfig,
|
|
12
|
+
} from '../../src/protocol.js';
|
|
13
|
+
import { onebot12RuntimeStateToken } from '../../src/onebot12-runtime-state.js';
|
|
14
|
+
|
|
15
|
+
export { OneBot12WebhookEndpoint } from '../../src/webhook.js';
|
|
16
|
+
export type { OneBot12WebhookEndpointOptions } from '../../src/webhook.js';
|
|
17
|
+
export { OneBot12WsEndpoint } from '../../src/ws-endpoint.js';
|
|
18
|
+
export type { OneBot12WsEndpointOptions } from '../../src/ws-endpoint.js';
|
|
19
|
+
export { OneBot12WssEndpoint } from '../../src/wss-endpoint.js';
|
|
20
|
+
export type { OneBot12WssEndpointOptions } from '../../src/wss-endpoint.js';
|
|
21
|
+
export type { OneBot12WsSocket, OneBot12WsCreateOptions } from '../../src/ws-types.js';
|
|
22
|
+
|
|
23
|
+
declare module '@zhin.js/core' {
|
|
24
|
+
interface AdapterEndpoints {
|
|
25
|
+
onebot12: import('../../src/ws-endpoint.js').OneBot12WsEndpoint;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default defineAdapter<OneBot12EndpointConfig>({
|
|
30
|
+
capabilities: ['inbound', 'outbound'],
|
|
31
|
+
operations: ['recall'],
|
|
32
|
+
// 媒体段经 upload_file 物化为 file_id(spec 正式投递);上传失败降级扩展字段透传。
|
|
33
|
+
// 无卡片交互面,交互段降级纯文本。
|
|
34
|
+
segments: {
|
|
35
|
+
outboundMedia: ['url', 'path', 'base64', 'upload'],
|
|
36
|
+
interactive: 'text',
|
|
37
|
+
},
|
|
38
|
+
create(context) {
|
|
39
|
+
const config = resolveOneBot12Config(context.config);
|
|
40
|
+
// 注册到插件运行时状态(onebot12 endpoint list 的"运行中"数据源)
|
|
41
|
+
context.use(onebot12RuntimeStateToken).endpoints.set(config.id, {
|
|
42
|
+
id: config.id,
|
|
43
|
+
mode: config.connection,
|
|
44
|
+
});
|
|
45
|
+
if (config.connection === 'webhook') {
|
|
46
|
+
return new OneBot12WebhookEndpoint({
|
|
47
|
+
id: context.id,
|
|
48
|
+
http: context.use(httpHostToken),
|
|
49
|
+
config,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (config.connection === 'wss') {
|
|
53
|
+
return new OneBot12WssEndpoint({
|
|
54
|
+
id: context.id,
|
|
55
|
+
http: context.use(httpHostToken),
|
|
56
|
+
config,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return new OneBot12WsEndpoint({
|
|
60
|
+
id: context.id,
|
|
61
|
+
config,
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
/**
|
|
3
|
+
* `onebot12 endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
4
|
+
* commands/onebot12/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
5
|
+
*/
|
|
6
|
+
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
7
|
+
import { defineCommand } from 'zhin.js/command';
|
|
8
|
+
import { onebot12RuntimeStateToken } from "../../../lib/onebot12-runtime-state.js";
|
|
9
|
+
export const onebot12EndpointCommands = createEndpointCommands({
|
|
10
|
+
adapterKey: 'onebot12',
|
|
11
|
+
adapterDisplayName: 'OneBot 12',
|
|
12
|
+
fields: [
|
|
13
|
+
{ key: 'url', description: 'OneBot 实现 WebSocket URL(connection: ws 必填)' },
|
|
14
|
+
{ key: 'path', description: 'HTTP/WS 路径(webhook / reverse-wss)' },
|
|
15
|
+
{ key: 'api_url', description: 'HTTP action 端点(connection: webhook 出站必填)' },
|
|
16
|
+
{ key: 'access_token', env: true, description: 'OneBot access token' },
|
|
17
|
+
],
|
|
18
|
+
running: (use) => use(onebot12RuntimeStateToken).endpoints.values(),
|
|
19
|
+
describeEntry: (entry) => {
|
|
20
|
+
if (entry.url)
|
|
21
|
+
return `url: ${String(entry.url)}`;
|
|
22
|
+
if (entry.path)
|
|
23
|
+
return `path: ${String(entry.path)}`;
|
|
24
|
+
return '';
|
|
25
|
+
},
|
|
26
|
+
}, defineCommand);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `onebot12 endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
3
|
+
* commands/onebot12/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
4
|
+
*/
|
|
5
|
+
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
6
|
+
import { defineCommand } from 'zhin.js/command';
|
|
7
|
+
import { onebot12RuntimeStateToken } from '../../../src/onebot12-runtime-state.js';
|
|
8
|
+
|
|
9
|
+
export const onebot12EndpointCommands = createEndpointCommands({
|
|
10
|
+
adapterKey: 'onebot12',
|
|
11
|
+
adapterDisplayName: 'OneBot 12',
|
|
12
|
+
fields: [
|
|
13
|
+
{ key: 'url', description: 'OneBot 实现 WebSocket URL(connection: ws 必填)' },
|
|
14
|
+
{ key: 'path', description: 'HTTP/WS 路径(webhook / reverse-wss)' },
|
|
15
|
+
{ key: 'api_url', description: 'HTTP action 端点(connection: webhook 出站必填)' },
|
|
16
|
+
{ key: 'access_token', env: true, description: 'OneBot access token' },
|
|
17
|
+
],
|
|
18
|
+
running: (use) => use(onebot12RuntimeStateToken).endpoints.values(),
|
|
19
|
+
describeEntry: (entry) => {
|
|
20
|
+
if (entry.url) return `url: ${String(entry.url)}`;
|
|
21
|
+
if (entry.path) return `path: ${String(entry.path)}`;
|
|
22
|
+
return '';
|
|
23
|
+
},
|
|
24
|
+
}, defineCommand);
|
package/lib/client.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OneBotV12Client, type OneBotV12Event as ImHelperOneBot12Event, type OneBotV12Response } from '@imhelper/onebot-v12';
|
|
2
|
+
import { type EventMap, type ImHelperEventMap } from 'imhelper';
|
|
3
|
+
import { type ClientEventPayloads } from 'zhin.js/adapter';
|
|
4
|
+
import type { ResolvedOneBot12Config } from './protocol.js';
|
|
5
|
+
export { OneBotV12Client as Onebot12Client } from '@imhelper/onebot-v12';
|
|
6
|
+
export type Onebot12ApiCall = (action: string, params?: Record<string, unknown>) => Promise<OneBotV12Response>;
|
|
7
|
+
type Onebot12ClientEvents = ImHelperEventMap<string, ImHelperOneBot12Event, EventMap<string>>;
|
|
8
|
+
export type Onebot12ClientEventMap = ClientEventPayloads<Onebot12ClientEvents>;
|
|
9
|
+
export declare function createOnebot12EndpointClient(config: ResolvedOneBot12Config, request: Onebot12ApiCall): OneBotV12Client;
|
|
10
|
+
export declare function callOnebot12Client<T = unknown>(client: OneBotV12Client, action: string, params?: Record<string, unknown>): Promise<T | undefined>;
|
|
11
|
+
export declare function forwardOnebot12ClientEvents(client: OneBotV12Client, receive: (name: string, payload: unknown) => void): () => void;
|
|
12
|
+
declare module '@zhin.js/feature-kit' {
|
|
13
|
+
interface AdapterClientRegistry {
|
|
14
|
+
readonly onebot12: {
|
|
15
|
+
readonly client: OneBotV12Client;
|
|
16
|
+
readonly events: Onebot12ClientEventMap;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export declare const onebot12Client: import("@zhin.js/adapter").EndpointClientToken<OneBotV12Client, ClientEventPayloads<Onebot12ClientEvents>>;
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { OneBotV12Client, } from '@imhelper/onebot-v12';
|
|
2
|
+
import { EventFactory } from 'imhelper';
|
|
3
|
+
import { defineEndpointClient, forwardEndpointClientEvents, } from 'zhin.js/adapter';
|
|
4
|
+
export { OneBotV12Client as Onebot12Client } from '@imhelper/onebot-v12';
|
|
5
|
+
export function createOnebot12EndpointClient(config, request) {
|
|
6
|
+
const baseUrl = config.connection === 'ws'
|
|
7
|
+
? config.url.replace(/^ws(s?):/, 'http$1:')
|
|
8
|
+
: config.connection === 'webhook'
|
|
9
|
+
? config.api_url
|
|
10
|
+
: 'http://localhost';
|
|
11
|
+
return new OneBotV12Client({
|
|
12
|
+
baseUrl,
|
|
13
|
+
selfId: config.id,
|
|
14
|
+
accessToken: config.access_token,
|
|
15
|
+
receiveMode: 'manual',
|
|
16
|
+
call: request,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export async function callOnebot12Client(client, action, params) {
|
|
20
|
+
const response = await client.call(action, params);
|
|
21
|
+
if (response.status !== 'ok') {
|
|
22
|
+
throw new Error(`OneBot 12 API ${action}: retcode=${response.retcode}${response.message ? ` ${response.message}` : ''}`);
|
|
23
|
+
}
|
|
24
|
+
return response.data;
|
|
25
|
+
}
|
|
26
|
+
const onebot12ClientEventNames = Object.freeze([
|
|
27
|
+
...EventFactory.getSupportedEventTypes(),
|
|
28
|
+
'event',
|
|
29
|
+
]);
|
|
30
|
+
export function forwardOnebot12ClientEvents(client, receive) {
|
|
31
|
+
return forwardEndpointClientEvents(client, onebot12ClientEventNames, receive);
|
|
32
|
+
}
|
|
33
|
+
export const onebot12Client = defineEndpointClient('onebot12');
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export function createOneBot12ContentPort(callApi) {
|
|
2
|
+
return Object.freeze({
|
|
3
|
+
async resolve(reference, context) {
|
|
4
|
+
try {
|
|
5
|
+
context.signal.throwIfAborted();
|
|
6
|
+
if (reference.kind === 'forward') {
|
|
7
|
+
return Object.freeze({ status: 'unsupported', code: 'onebot12_forward_lookup_not_standardized' });
|
|
8
|
+
}
|
|
9
|
+
if (reference.kind === 'media') {
|
|
10
|
+
return reference.media.kind === 'file'
|
|
11
|
+
? Object.freeze({ status: 'unsupported', code: 'onebot12_opaque_media' })
|
|
12
|
+
: Object.freeze({ status: 'resolved', reference, value: reference.media });
|
|
13
|
+
}
|
|
14
|
+
const row = await callApi('get_message', { message_id: reference.message.id });
|
|
15
|
+
context.signal.throwIfAborted();
|
|
16
|
+
const message = (row.message && typeof row.message === 'object' ? row.message : row);
|
|
17
|
+
const segments = normalizeSegments(message.message ?? message.content);
|
|
18
|
+
const value = Object.freeze({
|
|
19
|
+
ref: reference.message,
|
|
20
|
+
...(message.user_id != null ? { actor: Object.freeze({ id: String(message.user_id) }) } : {}),
|
|
21
|
+
segments,
|
|
22
|
+
timestamp: toMillis(message.time),
|
|
23
|
+
});
|
|
24
|
+
return Object.freeze({ status: 'resolved', reference, value });
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (context.signal.aborted)
|
|
28
|
+
return Object.freeze({ status: 'expired', code: 'turn_aborted' });
|
|
29
|
+
return Object.freeze({ status: 'failed', code: 'onebot12_content_resolution_failed', message: error instanceof Error ? error.message : String(error) });
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function normalizeSegments(value) {
|
|
35
|
+
if (!Array.isArray(value))
|
|
36
|
+
return Object.freeze([{ type: 'text', data: Object.freeze({ text: String(value ?? '') }) }]);
|
|
37
|
+
return Object.freeze(value.map((item) => {
|
|
38
|
+
const row = item;
|
|
39
|
+
return Object.freeze({ type: String(row.type ?? 'text'), data: Object.freeze((row.data ?? {})) });
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
function toMillis(value) {
|
|
43
|
+
const time = Number(value);
|
|
44
|
+
return Number.isFinite(time) ? (time < 10_000_000_000 ? time * 1000 : time) : Date.now();
|
|
45
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OneBot12 endpoint management 语义端口(Console 社交面 RPC 消费,见
|
|
3
|
+
* packages/im/adapter/src/endpoint-management.ts)。
|
|
4
|
+
*
|
|
5
|
+
* 动作名对齐 OB12 规范:get_friend_list / get_group_list / get_group_member_list。
|
|
6
|
+
* 归一化取舍(OB12 id 为字符串,收敛为数字):
|
|
7
|
+
* - friend → {user_id:number, nickname: user_name, remark: user_displayname ?? ''}
|
|
8
|
+
* - group → {group_id:number, name: group_name ?? name}
|
|
9
|
+
* - 群成员列表保持 OB12 原生形状,仅保证数组
|
|
10
|
+
*/
|
|
11
|
+
import type { EndpointManagement } from 'zhin.js/adapter';
|
|
12
|
+
/** 管理面只依赖 endpoint 的 callApi(ws/wss/webhook 三种传输各自实现)。 */
|
|
13
|
+
export interface OneBot12ManagementCaller {
|
|
14
|
+
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createOneBot12EndpointManagement(endpoint: OneBot12ManagementCaller): EndpointManagement;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function createOneBot12EndpointManagement(endpoint) {
|
|
2
|
+
return Object.freeze({
|
|
3
|
+
async listFriends() {
|
|
4
|
+
const data = await endpoint.callApi('get_friend_list');
|
|
5
|
+
return toArray(data).map((value) => {
|
|
6
|
+
const friend = asRecord(value);
|
|
7
|
+
return {
|
|
8
|
+
user_id: toNumberId(friend.user_id, 'user_id'),
|
|
9
|
+
nickname: String(friend.user_name ?? friend.nickname ?? ''),
|
|
10
|
+
remark: String(friend.user_displayname ?? friend.remark ?? ''),
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
async listGroups() {
|
|
15
|
+
const data = await endpoint.callApi('get_group_list');
|
|
16
|
+
return toArray(data).map((value) => {
|
|
17
|
+
const group = asRecord(value);
|
|
18
|
+
return {
|
|
19
|
+
group_id: toNumberId(group.group_id, 'group_id'),
|
|
20
|
+
name: String(group.group_name ?? group.name ?? ''),
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
async listGroupMembers(groupId) {
|
|
25
|
+
const data = await endpoint.callApi('get_group_member_list', {
|
|
26
|
+
group_id: groupId,
|
|
27
|
+
});
|
|
28
|
+
return toArray(data);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function asRecord(value) {
|
|
33
|
+
return value !== null && typeof value === 'object'
|
|
34
|
+
? value
|
|
35
|
+
: {};
|
|
36
|
+
}
|
|
37
|
+
function toArray(value) {
|
|
38
|
+
return Array.isArray(value) ? value : [];
|
|
39
|
+
}
|
|
40
|
+
/** OB12 id 是字符串;QQ 系实现均为数字串,统一收敛为数字。 */
|
|
41
|
+
function toNumberId(value, label) {
|
|
42
|
+
const n = Number(value);
|
|
43
|
+
if (!Number.isFinite(n) || String(value ?? '').trim() === '') {
|
|
44
|
+
throw new TypeError(`onebot12 ${label} 必须是数字: ${String(value)}`);
|
|
45
|
+
}
|
|
46
|
+
return n;
|
|
47
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
interface Contexts {
|
|
12
|
-
router: import('@zhin.js/host-router').Router;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
interface Adapters {
|
|
16
|
-
onebot12: OneBot12Adapter;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1
|
+
export { buildSendMessageParams, buildWsConnectOptions, callOneBot12Action, formatInboundContent, formatOutboundSegments, getChannelId, isBotMentioned, isMessageEvent, mediaRefToOneBot12Fields, mediaRefToOneBot12UploadParams, onebot12InboundConversation, resolveOneBot12Config, senderNickname, senderUserId, uploadOneBot12MediaSegments, type OneBot12ActionRequest, type OneBot12ActionResponse, type OneBot12CallAction, type OneBot12ConfigBase, type OneBot12EndpointConfig, type OneBot12Event, type OneBot12HttpOptions, type OneBot12Segment, type OneBot12Self, type OneBot12WebhookConfig, type OneBot12WireSegment, type OneBot12WsConfig, type OneBot12WssConfig, type ResolvedOneBot12Config, } from './protocol.js';
|
|
2
|
+
export { OneBot12WebhookEndpoint, type OneBot12WebhookEndpointOptions, } from './webhook.js';
|
|
3
|
+
export { OneBot12WsEndpoint, type OneBot12WsEndpointOptions, } from './ws-endpoint.js';
|
|
4
|
+
export { OneBot12WssEndpoint, type OneBot12WssEndpointOptions, } from './wss-endpoint.js';
|
|
5
|
+
export type { OneBot12WsSocket, OneBot12WsCreateOptions } from './ws-types.js';
|
|
6
|
+
export { verifyOneBotAccessToken } from './wss-auth.js';
|
|
7
|
+
export { Onebot12Client, onebot12Client, type Onebot12ClientEventMap, } from './client.js';
|
|
8
|
+
export type { OneBotV12ActionUrlResolver, OneBotV12AdapterConfig as ImHelperOneBotV12AdapterConfig, OneBotV12Call, OneBotV12ClientConfig, OneBotV12Event as ImHelperOneBotV12Event, OneBotV12Response, } from '@imhelper/onebot-v12';
|
|
9
|
+
export { ProtocolError } from '@imhelper/onebot-v12';
|
|
10
|
+
export type { ProtocolErrorKind, ProtocolErrorOptions } from 'imhelper';
|
package/lib/index.js
CHANGED
|
@@ -1,27 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export
|
|
8
|
-
export { callOneBot12Action } from './api.js';
|
|
9
|
-
export * from './utils.js';
|
|
10
|
-
export { OneBot12WsClient } from './endpoint-ws.js';
|
|
11
|
-
export { OneBot12WebhookEndpoint } from './endpoint-webhook.js';
|
|
12
|
-
export { OneBot12WssServer } from './endpoint-wss.js';
|
|
13
|
-
export { OneBot12Adapter } from './adapter.js';
|
|
14
|
-
const { provide } = usePlugin();
|
|
15
|
-
provide({
|
|
16
|
-
name: 'onebot12',
|
|
17
|
-
description: 'OneBot 12 协议适配器(正向 WS / Webhook / 反向 WS)',
|
|
18
|
-
mounted: async (p) => {
|
|
19
|
-
const adapter = new OneBot12Adapter(p);
|
|
20
|
-
await adapter.start();
|
|
21
|
-
return adapter;
|
|
22
|
-
},
|
|
23
|
-
dispose: async (adapter) => {
|
|
24
|
-
await adapter.stop();
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export { buildSendMessageParams, buildWsConnectOptions, callOneBot12Action, formatInboundContent, formatOutboundSegments, getChannelId, isBotMentioned, isMessageEvent, mediaRefToOneBot12Fields, mediaRefToOneBot12UploadParams, onebot12InboundConversation, resolveOneBot12Config, senderNickname, senderUserId, uploadOneBot12MediaSegments, } from './protocol.js';
|
|
2
|
+
export { OneBot12WebhookEndpoint, } from './webhook.js';
|
|
3
|
+
export { OneBot12WsEndpoint, } from './ws-endpoint.js';
|
|
4
|
+
export { OneBot12WssEndpoint, } from './wss-endpoint.js';
|
|
5
|
+
export { verifyOneBotAccessToken } from './wss-auth.js';
|
|
6
|
+
export { Onebot12Client, onebot12Client, } from './client.js';
|
|
7
|
+
export { ProtocolError } from '@imhelper/onebot-v12';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const onebot12RuntimeStateToken: import("zhin.js").Token<import("@zhin.js/adapter").EndpointRuntimeState>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OneBot12 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
|
|
3
|
+
* 由 plugin.ts setup() provide,adapter create 与 `onebot12 endpoint` 命令共享(同一 owner generation)。
|
|
4
|
+
*/
|
|
5
|
+
import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
|
|
6
|
+
export const onebot12RuntimeStateToken = defineEndpointRuntimeStateToken('onebot12');
|