@zhin.js/adapter-onebot11 6.0.2 → 6.0.5
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 +95 -0
- package/README.md +3 -3
- package/adapters/onebot11.js +2 -2
- package/adapters/onebot11.ts +2 -2
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/onebot11-agent-deps.d.ts +2 -2
- package/lib/onebot11-agent-deps.js +7 -7
- package/lib/protocol.d.ts +20 -13
- package/lib/protocol.js +33 -41
- package/lib/ws-endpoint.d.ts +2 -5
- package/lib/ws-endpoint.js +33 -25
- package/lib/ws-transport.d.ts +1 -1
- package/lib/ws-transport.js +1 -1
- package/lib/wss-endpoint.d.ts +2 -5
- package/lib/wss-endpoint.js +29 -21
- package/package.json +16 -14
- package/plugin.js +5 -4
- package/schema.json +41 -5
- package/src/index.ts +1 -3
- package/src/onebot11-agent-deps.ts +8 -8
- package/src/protocol.ts +48 -53
- package/src/ws-endpoint.ts +36 -26
- package/src/ws-transport.ts +2 -2
- package/src/wss-endpoint.ts +32 -23
- /package/commands/endpoint/add/{[name:string].js → [id].js} +0 -0
- /package/commands/endpoint/add/{[name:string].ts → [id].ts} +0 -0
- /package/commands/endpoint/remove/{[name:string].js → [id].js} +0 -0
- /package/commands/endpoint/remove/{[name:string].ts → [id].ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,100 @@
|
|
|
1
1
|
# @zhin.js/adapter-onebot11
|
|
2
2
|
|
|
3
|
+
## 6.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 51015d6: refactor(adapters): migrate platform-permit to PermissionSubject
|
|
8
|
+
|
|
9
|
+
All adapter platform-permit checkers now accept PermissionSubject
|
|
10
|
+
(duck-typed from Message/CommandSession) instead of Message directly.
|
|
11
|
+
registerPlatformPermitChecker is replaced by host.registerPlatform in
|
|
12
|
+
the adapter plugin setup. activity-feedback service updated for new
|
|
13
|
+
PermissionHost integration.
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [6f9c366]
|
|
16
|
+
- Updated dependencies [373a56b]
|
|
17
|
+
- Updated dependencies [0de46a8]
|
|
18
|
+
- Updated dependencies [c106ecc]
|
|
19
|
+
- Updated dependencies [ca92e03]
|
|
20
|
+
- Updated dependencies [b0f37ae]
|
|
21
|
+
- Updated dependencies [ba08a2f]
|
|
22
|
+
- Updated dependencies [b08f7fe]
|
|
23
|
+
- Updated dependencies [daffd4c]
|
|
24
|
+
- Updated dependencies [36c7400]
|
|
25
|
+
- Updated dependencies [a9fa72e]
|
|
26
|
+
- Updated dependencies [c8de3ef]
|
|
27
|
+
- Updated dependencies [60f0fc8]
|
|
28
|
+
- Updated dependencies [574c990]
|
|
29
|
+
- Updated dependencies [d096f16]
|
|
30
|
+
- Updated dependencies [3f29623]
|
|
31
|
+
- Updated dependencies [2916852]
|
|
32
|
+
- Updated dependencies [d047869]
|
|
33
|
+
- Updated dependencies [162fa34]
|
|
34
|
+
- Updated dependencies [e62561e]
|
|
35
|
+
- Updated dependencies [3eeeb46]
|
|
36
|
+
- Updated dependencies [85d0f82]
|
|
37
|
+
- Updated dependencies [61bfc1c]
|
|
38
|
+
- Updated dependencies [04bad47]
|
|
39
|
+
- Updated dependencies [e40b048]
|
|
40
|
+
- Updated dependencies [5a5b1bb]
|
|
41
|
+
- Updated dependencies [f1708c3]
|
|
42
|
+
- Updated dependencies [d254a81]
|
|
43
|
+
- Updated dependencies [7123c47]
|
|
44
|
+
- Updated dependencies [05befc1]
|
|
45
|
+
- Updated dependencies [0663b6a]
|
|
46
|
+
- Updated dependencies [f28f9b3]
|
|
47
|
+
- Updated dependencies [9f340f7]
|
|
48
|
+
- Updated dependencies [e53444f]
|
|
49
|
+
- Updated dependencies [5eedd26]
|
|
50
|
+
- Updated dependencies [92b0dd7]
|
|
51
|
+
- Updated dependencies [f919b6f]
|
|
52
|
+
- Updated dependencies [098e411]
|
|
53
|
+
- Updated dependencies [e1b7c01]
|
|
54
|
+
- Updated dependencies [9b94f87]
|
|
55
|
+
- Updated dependencies [a7df753]
|
|
56
|
+
- @zhin.js/agent@1.1.5
|
|
57
|
+
- @zhin.js/host-http@1.0.8
|
|
58
|
+
- @zhin.js/permission@1.0.1
|
|
59
|
+
- @zhin.js/im-contract@1.0.3
|
|
60
|
+
- @zhin.js/adapter@1.1.7
|
|
61
|
+
- @zhin.js/plugin-runtime@1.1.5
|
|
62
|
+
- @zhin.js/command@1.0.9
|
|
63
|
+
- @zhin.js/core@1.5.4
|
|
64
|
+
- zhin.js@6.0.4
|
|
65
|
+
|
|
66
|
+
## 6.0.4
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- f8c7a54: fix: im
|
|
71
|
+
- Updated dependencies [f8c7a54]
|
|
72
|
+
- @zhin.js/logger@1.0.76
|
|
73
|
+
- @zhin.js/host-http@1.0.7
|
|
74
|
+
- @zhin.js/adapter@1.1.6
|
|
75
|
+
- @zhin.js/agent@1.1.4
|
|
76
|
+
- @zhin.js/command@1.0.8
|
|
77
|
+
- @zhin.js/core@1.5.3
|
|
78
|
+
- @zhin.js/im-contract@1.0.2
|
|
79
|
+
- @zhin.js/plugin-runtime@1.1.4
|
|
80
|
+
- zhin.js@6.0.3
|
|
81
|
+
|
|
82
|
+
## 6.0.3
|
|
83
|
+
|
|
84
|
+
### Patch Changes
|
|
85
|
+
|
|
86
|
+
- Updated dependencies [afc0e66]
|
|
87
|
+
- Updated dependencies [2e41ad5]
|
|
88
|
+
- Updated dependencies [9f57124]
|
|
89
|
+
- @zhin.js/core@1.5.2
|
|
90
|
+
- @zhin.js/adapter@1.1.5
|
|
91
|
+
- @zhin.js/im-contract@1.0.1
|
|
92
|
+
- @zhin.js/plugin-runtime@1.1.3
|
|
93
|
+
- @zhin.js/command@1.0.7
|
|
94
|
+
- @zhin.js/host-http@1.0.6
|
|
95
|
+
- @zhin.js/agent@1.1.3
|
|
96
|
+
- zhin.js@6.0.2
|
|
97
|
+
|
|
3
98
|
## 6.0.2
|
|
4
99
|
|
|
5
100
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Zhin.js [OneBot 11](https://github.com/botuniverse/onebot-11) 适配器(Plugin
|
|
|
8
8
|
- 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
|
|
9
9
|
- **正向 WebSocket**(`connection: ws`):应用连 OneBot 实现的 WS 服务器
|
|
10
10
|
- `access_token` 鉴权(Bearer + query)
|
|
11
|
-
- 入站经 `messageGatewayToken`;出站 `send({
|
|
11
|
+
- 入站经 `messageGatewayToken`;出站 `send({ conversation, payload })`
|
|
12
12
|
|
|
13
13
|
## 安装
|
|
14
14
|
|
|
@@ -23,8 +23,8 @@ pnpm add @zhin.js/adapter-onebot11
|
|
|
23
23
|
- `@zhin.js/plugin-runtime` — `plugin.ts`(`definePlugin`)
|
|
24
24
|
- 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
|
|
25
25
|
|
|
26
|
-
入站:`gateway.receive({
|
|
27
|
-
出站:`send({
|
|
26
|
+
入站:`gateway.receive({ conversation, message, content, sender, metadata })`(`conversation.kind` 为 `private`/`group`,`id` 为 uid/gid)
|
|
27
|
+
出站:`send({ conversation, payload })` → WS `send_private_msg` / `send_group_msg`(payload 已由 gateway/core 渲染;无 segment-mapper)
|
|
28
28
|
|
|
29
29
|
## 最小配置
|
|
30
30
|
|
package/adapters/onebot11.js
CHANGED
|
@@ -22,8 +22,8 @@ export default defineAdapter({
|
|
|
22
22
|
const config = resolveOneBot11Config(context.config);
|
|
23
23
|
const gateway = context.use(messageGatewayToken);
|
|
24
24
|
// 注册到插件运行时状态(onebot11.endpoint list 的"运行中"数据源)
|
|
25
|
-
context.use(onebot11RuntimeStateToken).endpoints.set(config.
|
|
26
|
-
|
|
25
|
+
context.use(onebot11RuntimeStateToken).endpoints.set(config.id, {
|
|
26
|
+
id: config.id,
|
|
27
27
|
mode: config.connection,
|
|
28
28
|
});
|
|
29
29
|
if (config.connection === 'wss') {
|
package/adapters/onebot11.ts
CHANGED
|
@@ -29,8 +29,8 @@ export default defineAdapter<OneBot11AdapterConfig>({
|
|
|
29
29
|
const config = resolveOneBot11Config(context.config);
|
|
30
30
|
const gateway = context.use(messageGatewayToken);
|
|
31
31
|
// 注册到插件运行时状态(onebot11.endpoint list 的"运行中"数据源)
|
|
32
|
-
context.use(onebot11RuntimeStateToken).endpoints.set(config.
|
|
33
|
-
|
|
32
|
+
context.use(onebot11RuntimeStateToken).endpoints.set(config.id, {
|
|
33
|
+
id: config.id,
|
|
34
34
|
mode: config.connection,
|
|
35
35
|
});
|
|
36
36
|
if (config.connection === 'wss') {
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata,
|
|
1
|
+
export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata, formatOutboundSegments, getChannelId, isMessageEvent, isOneBot11BotMentioned, mediaRefToOneBotFile, onebot11InboundConversation, resolveOneBot11Config, senderDisplayName, senderNickname, senderUserId, type OneBot11ActionRequest, type OneBot11ActionResponse, type OneBot11AdapterConfig, type OneBot11ConfigBase, type OneBot11EndpointConfig, type OneBot11Event, type OneBot11Segment, type OneBot11Sender, type OneBot11WireSegment, type OneBot11WsConfig, type OneBot11WssConfig, type ResolvedOneBot11Config, } from './protocol.js';
|
|
2
2
|
export { OneBot11WsEndpoint, type OneBot11WsEndpointOptions, } from './ws-endpoint.js';
|
|
3
3
|
export { OneBot11WssEndpoint, type OneBot11WssEndpointOptions, } from './wss-endpoint.js';
|
|
4
4
|
export type { OneBot11WsSocket, OneBot11WsCreateOptions } from './ws-types.js';
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata,
|
|
1
|
+
export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata, formatOutboundSegments, getChannelId, isMessageEvent, isOneBot11BotMentioned, mediaRefToOneBotFile, onebot11InboundConversation, resolveOneBot11Config, senderDisplayName, senderNickname, senderUserId, } from './protocol.js';
|
|
2
2
|
export { OneBot11WsEndpoint, } from './ws-endpoint.js';
|
|
3
3
|
export { OneBot11WssEndpoint, } from './wss-endpoint.js';
|
|
4
4
|
export { callOneBot11WsAction, decodeWsPayload, handleOneBot11WsMessage, rejectAllPending, startOneBot11Heartbeat, } from './ws-transport.js';
|
|
@@ -7,9 +7,9 @@ export interface Onebot11AgentEndpoint {
|
|
|
7
7
|
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
8
8
|
}
|
|
9
9
|
export interface Onebot11AgentDeps {
|
|
10
|
-
getEndpoint: (
|
|
10
|
+
getEndpoint: (endpointKey: string) => Onebot11AgentEndpoint;
|
|
11
11
|
}
|
|
12
|
-
export declare function registerOnebot11AgentEndpoint(
|
|
12
|
+
export declare function registerOnebot11AgentEndpoint(endpointKey: string, endpoint: Onebot11AgentEndpoint): () => void;
|
|
13
13
|
/** Optional override used by tests / transitional callers. */
|
|
14
14
|
export declare function setOnebot11AgentDeps(deps: Onebot11AgentDeps): void;
|
|
15
15
|
export declare function getOnebot11AgentDeps(): Onebot11AgentDeps;
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const endpoints = new Map();
|
|
6
6
|
let override = null;
|
|
7
|
-
export function registerOnebot11AgentEndpoint(
|
|
8
|
-
endpoints.set(
|
|
7
|
+
export function registerOnebot11AgentEndpoint(endpointKey, endpoint) {
|
|
8
|
+
endpoints.set(endpointKey, endpoint);
|
|
9
9
|
return () => {
|
|
10
|
-
if (endpoints.get(
|
|
11
|
-
endpoints.delete(
|
|
10
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
11
|
+
endpoints.delete(endpointKey);
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -20,10 +20,10 @@ export function getOnebot11AgentDeps() {
|
|
|
20
20
|
if (override)
|
|
21
21
|
return override;
|
|
22
22
|
return {
|
|
23
|
-
getEndpoint(
|
|
24
|
-
const registered = endpoints.get(
|
|
23
|
+
getEndpoint(endpointKey) {
|
|
24
|
+
const registered = endpoints.get(endpointKey);
|
|
25
25
|
if (!registered)
|
|
26
|
-
throw new Error(`Endpoint ${
|
|
26
|
+
throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
27
27
|
return registered;
|
|
28
28
|
},
|
|
29
29
|
};
|
package/lib/protocol.d.ts
CHANGED
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
* Spec: https://github.com/botuniverse/onebot-11
|
|
5
5
|
*/
|
|
6
6
|
import { type MediaRef } from '@zhin.js/core';
|
|
7
|
+
import type { ConversationRef } from '@zhin.js/im-contract';
|
|
7
8
|
/** Transitional legacy endpoint row (`endpoints[]` with `context: onebot11`). */
|
|
8
9
|
export interface OneBot11LegacyEndpointRow {
|
|
9
10
|
readonly context?: string;
|
|
10
11
|
readonly connection?: 'ws' | 'wss';
|
|
11
12
|
/** Legacy alias: `type: 'ws' | 'ws_reverse'` */
|
|
12
13
|
readonly type?: string;
|
|
13
|
-
readonly
|
|
14
|
+
readonly id?: string;
|
|
14
15
|
readonly access_token?: string;
|
|
15
16
|
readonly url?: string;
|
|
16
17
|
readonly path?: string;
|
|
@@ -20,7 +21,7 @@ export interface OneBot11LegacyEndpointRow {
|
|
|
20
21
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
21
22
|
export interface OneBot11AdapterConfig {
|
|
22
23
|
readonly connection?: 'ws' | 'wss';
|
|
23
|
-
readonly
|
|
24
|
+
readonly id?: string;
|
|
24
25
|
readonly access_token?: string;
|
|
25
26
|
readonly url?: string;
|
|
26
27
|
readonly path?: string;
|
|
@@ -31,7 +32,7 @@ export interface OneBot11AdapterConfig {
|
|
|
31
32
|
}
|
|
32
33
|
export interface OneBot11ConfigBase {
|
|
33
34
|
readonly context: 'onebot11';
|
|
34
|
-
readonly
|
|
35
|
+
readonly id: string;
|
|
35
36
|
readonly access_token?: string;
|
|
36
37
|
}
|
|
37
38
|
/** 正向 WebSocket:应用连 OneBot 实现的 WS 服务器 */
|
|
@@ -90,10 +91,6 @@ export interface OneBot11WireSegment {
|
|
|
90
91
|
readonly type: string;
|
|
91
92
|
readonly data?: Record<string, unknown>;
|
|
92
93
|
}
|
|
93
|
-
export interface ParsedSendTarget {
|
|
94
|
-
readonly message_type: 'private' | 'group';
|
|
95
|
-
readonly id: string;
|
|
96
|
-
}
|
|
97
94
|
export declare function resolveOneBot11Config(config?: OneBot11AdapterConfig): ResolvedOneBot11Config;
|
|
98
95
|
/** 判断是否为消息事件(post_type=message) */
|
|
99
96
|
export declare function isMessageEvent(ev: OneBot11Event): ev is OneBot11Event & {
|
|
@@ -102,10 +99,11 @@ export declare function isMessageEvent(ev: OneBot11Event): ev is OneBot11Event &
|
|
|
102
99
|
/** 从事件得到场景 id:私聊 user_id,群 group_id */
|
|
103
100
|
export declare function getChannelId(ev: OneBot11Event): string;
|
|
104
101
|
/**
|
|
105
|
-
*
|
|
102
|
+
* 入站归一化 → ConversationRef:OneBot 11 `group` 消息 → kind 'group',
|
|
103
|
+
* 其余(private 及带 group_id 的非 private 事件按群处理)→ kind 'private'。
|
|
104
|
+
* OneBot 11 无 guild/temp 容器概念,不填 parent。
|
|
106
105
|
*/
|
|
107
|
-
export declare function
|
|
108
|
-
export declare function parseSendTarget(target: string): ParsedSendTarget;
|
|
106
|
+
export declare function onebot11InboundConversation(endpointKey: string, ev: OneBot11Event): ConversationRef;
|
|
109
107
|
/** Build inbound text for MessageGateway.receive */
|
|
110
108
|
export declare function formatInboundContent(ev: OneBot11Event): string;
|
|
111
109
|
export declare function senderDisplayName(ev: OneBot11Event): string;
|
|
@@ -126,8 +124,17 @@ export declare function isOneBot11BotMentioned(input: {
|
|
|
126
124
|
readonly selfId: string | undefined;
|
|
127
125
|
readonly message?: readonly OneBot11Segment[];
|
|
128
126
|
}): boolean;
|
|
129
|
-
/**
|
|
130
|
-
export
|
|
127
|
+
/** Inbound fields extracted from an event for gateway.receive (ws / wss 两个 endpoint 共用). */
|
|
128
|
+
export interface OneBot11InboundFields {
|
|
129
|
+
readonly metadata: Readonly<Record<string, unknown>>;
|
|
130
|
+
readonly endpointId: string;
|
|
131
|
+
readonly mentioned: boolean;
|
|
132
|
+
readonly replyTo: {
|
|
133
|
+
readonly id: string;
|
|
134
|
+
} | undefined;
|
|
135
|
+
}
|
|
136
|
+
/** 构造 gateway.receive 的 metadata 与提升字段(ws / wss 两个 endpoint 共用)。 */
|
|
137
|
+
export declare function formatInboundMetadata(ev: OneBot11Event, endpoint: string): OneBot11InboundFields;
|
|
131
138
|
/**
|
|
132
139
|
* canonical MediaRef → OneBot `file` 参数:url 直传、base64 → `base64://`、
|
|
133
140
|
* 本地路径 → `file://`(路径在 OneBot 实现侧解析)、kind=file 不透明引用原样透传。
|
|
@@ -140,7 +147,7 @@ export declare function mediaRefToOneBotFile(media: MediaRef): string;
|
|
|
140
147
|
* 其余 wire 形状段(at / 平台扩展段)原样透传。
|
|
141
148
|
*/
|
|
142
149
|
export declare function formatOutboundSegments(payload: unknown): OneBot11Segment[];
|
|
143
|
-
export declare function buildSendAction(
|
|
150
|
+
export declare function buildSendAction(conversation: ConversationRef, message: OneBot11Segment[]): {
|
|
144
151
|
action: string;
|
|
145
152
|
params: Record<string, unknown>;
|
|
146
153
|
};
|
package/lib/protocol.js
CHANGED
|
@@ -18,8 +18,8 @@ function normalizeConnection(connection, legacyType) {
|
|
|
18
18
|
export function resolveOneBot11Config(config = {}) {
|
|
19
19
|
const entry = config.endpoints?.find((item) => item.context === 'onebot11');
|
|
20
20
|
const connection = normalizeConnection(config.connection ?? entry?.connection, entry?.type);
|
|
21
|
-
const
|
|
22
|
-
|| (typeof entry?.
|
|
21
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
22
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
23
23
|
|| process.env.ONEBOT11_BOT_NAME
|
|
24
24
|
|| 'onebot11-bot';
|
|
25
25
|
const access_token = config.access_token ?? entry?.access_token;
|
|
@@ -31,7 +31,7 @@ export function resolveOneBot11Config(config = {}) {
|
|
|
31
31
|
return {
|
|
32
32
|
context: 'onebot11',
|
|
33
33
|
connection: 'ws',
|
|
34
|
-
|
|
34
|
+
id,
|
|
35
35
|
access_token,
|
|
36
36
|
url,
|
|
37
37
|
reconnect_interval: config.reconnect_interval ?? entry?.reconnect_interval ?? 5000,
|
|
@@ -46,7 +46,7 @@ export function resolveOneBot11Config(config = {}) {
|
|
|
46
46
|
return {
|
|
47
47
|
context: 'onebot11',
|
|
48
48
|
connection: 'wss',
|
|
49
|
-
|
|
49
|
+
id,
|
|
50
50
|
access_token,
|
|
51
51
|
path,
|
|
52
52
|
heartbeat_interval: config.heartbeat_interval ?? entry?.heartbeat_interval ?? 30_000,
|
|
@@ -69,28 +69,19 @@ export function getChannelId(ev) {
|
|
|
69
69
|
return '';
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
72
|
+
* 入站归一化 → ConversationRef:OneBot 11 `group` 消息 → kind 'group',
|
|
73
|
+
* 其余(private 及带 group_id 的非 private 事件按群处理)→ kind 'private'。
|
|
74
|
+
* OneBot 11 无 guild/temp 容器概念,不填 parent。
|
|
73
75
|
*/
|
|
74
|
-
export function
|
|
75
|
-
const
|
|
76
|
+
export function onebot11InboundConversation(endpointKey, ev) {
|
|
77
|
+
const kind = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private')
|
|
76
78
|
? 'group'
|
|
77
79
|
: 'private';
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return { message_type: 'private', id: target };
|
|
84
|
-
}
|
|
85
|
-
const head = target.slice(0, sep);
|
|
86
|
-
const rest = target.slice(sep + 1);
|
|
87
|
-
if (head === 'group') {
|
|
88
|
-
return { message_type: 'group', id: rest };
|
|
89
|
-
}
|
|
90
|
-
if (head === 'private') {
|
|
91
|
-
return { message_type: 'private', id: rest };
|
|
92
|
-
}
|
|
93
|
-
return { message_type: 'private', id: target };
|
|
80
|
+
return {
|
|
81
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
82
|
+
kind,
|
|
83
|
+
id: getChannelId(ev),
|
|
84
|
+
};
|
|
94
85
|
}
|
|
95
86
|
/** Build inbound text for MessageGateway.receive */
|
|
96
87
|
export function formatInboundContent(ev) {
|
|
@@ -153,24 +144,26 @@ export function isOneBot11BotMentioned(input) {
|
|
|
153
144
|
return qq !== 'all' && qq === input.selfId;
|
|
154
145
|
});
|
|
155
146
|
}
|
|
156
|
-
/** 构造 gateway.receive 的 metadata
|
|
147
|
+
/** 构造 gateway.receive 的 metadata 与提升字段(ws / wss 两个 endpoint 共用)。 */
|
|
157
148
|
export function formatInboundMetadata(ev, endpoint) {
|
|
158
149
|
const selfId = ev.self_id != null ? String(ev.self_id) : undefined;
|
|
159
150
|
const nickname = senderNickname(ev);
|
|
160
151
|
const quoteId = extractQuoteId(ev);
|
|
161
152
|
const mentioned = isOneBot11BotMentioned({ selfId, message: ev.message });
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
153
|
+
return {
|
|
154
|
+
metadata: Object.freeze({
|
|
155
|
+
message_type: ev.message_type,
|
|
156
|
+
user_id: ev.user_id != null ? String(ev.user_id) : undefined,
|
|
157
|
+
group_id: ev.group_id != null ? String(ev.group_id) : undefined,
|
|
158
|
+
time: ev.time,
|
|
159
|
+
self_id: selfId,
|
|
160
|
+
role: ev.sender?.role,
|
|
161
|
+
...(nickname ? { nickname } : {}),
|
|
162
|
+
}),
|
|
163
|
+
endpointId: endpoint,
|
|
164
|
+
mentioned,
|
|
165
|
+
replyTo: quoteId ? { id: quoteId } : undefined,
|
|
166
|
+
};
|
|
174
167
|
}
|
|
175
168
|
/**
|
|
176
169
|
* canonical MediaRef → OneBot `file` 参数:url 直传、base64 → `base64://`、
|
|
@@ -289,13 +282,12 @@ export function formatOutboundSegments(payload) {
|
|
|
289
282
|
}
|
|
290
283
|
return segs.length ? segs : [{ type: 'text', data: { text: '' } }];
|
|
291
284
|
}
|
|
292
|
-
export function buildSendAction(
|
|
293
|
-
|
|
294
|
-
if (parsed.message_type === 'group') {
|
|
285
|
+
export function buildSendAction(conversation, message) {
|
|
286
|
+
if (conversation.kind === 'group') {
|
|
295
287
|
return {
|
|
296
288
|
action: 'send_group_msg',
|
|
297
289
|
params: {
|
|
298
|
-
group_id: Number(
|
|
290
|
+
group_id: Number(conversation.id) || conversation.id,
|
|
299
291
|
message,
|
|
300
292
|
},
|
|
301
293
|
};
|
|
@@ -303,7 +295,7 @@ export function buildSendAction(target, message) {
|
|
|
303
295
|
return {
|
|
304
296
|
action: 'send_private_msg',
|
|
305
297
|
params: {
|
|
306
|
-
user_id: Number(
|
|
298
|
+
user_id: Number(conversation.id) || conversation.id,
|
|
307
299
|
message,
|
|
308
300
|
},
|
|
309
301
|
};
|
package/lib/ws-endpoint.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EndpointInstance, type EndpointManagement } from '@zhin.js/adapter';
|
|
1
|
+
import { type EndpointInstance, type EndpointManagement, type EndpointSendRequest } from '@zhin.js/adapter';
|
|
2
2
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
3
3
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
4
4
|
import { type OneBot11Event, type OneBot11WsConfig } from './protocol.js';
|
|
@@ -17,10 +17,7 @@ export declare class OneBot11WsEndpoint implements EndpointInstance {
|
|
|
17
17
|
open(): void;
|
|
18
18
|
close(): void;
|
|
19
19
|
stop(): Promise<void>;
|
|
20
|
-
send({
|
|
21
|
-
readonly target: string;
|
|
22
|
-
readonly payload: unknown;
|
|
23
|
-
}): Promise<string>;
|
|
20
|
+
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
24
21
|
recallMessage(messageId: string): Promise<void>;
|
|
25
22
|
/** Public API for agent tools / callers. */
|
|
26
23
|
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
package/lib/ws-endpoint.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import WebSocket from 'ws';
|
|
5
5
|
import { createEndpointLifecycle, } from '@zhin.js/adapter';
|
|
6
|
-
import { formatCompact,
|
|
6
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
7
7
|
import { createOneBot11EndpointManagement } from './endpoint-management.js';
|
|
8
8
|
import { registerOnebot11AgentEndpoint } from './onebot11-agent-deps.js';
|
|
9
|
-
import { buildSendAction, buildWsConnectOptions, formatInboundContent, formatInboundMetadata,
|
|
9
|
+
import { buildSendAction, buildWsConnectOptions, formatInboundContent, formatInboundMetadata, formatOutboundSegments, isMessageEvent, onebot11InboundConversation, senderDisplayName, senderUserId, } from './protocol.js';
|
|
10
10
|
import { callOneBot11WsAction, handleOneBot11WsMessage, rejectAllPending, } from './ws-transport.js';
|
|
11
|
-
const logger = getLogger('onebot11');
|
|
12
11
|
export class OneBot11WsEndpoint {
|
|
12
|
+
#logger;
|
|
13
13
|
#options;
|
|
14
14
|
management = createOneBot11EndpointManagement(this);
|
|
15
15
|
#lifecycle;
|
|
@@ -19,10 +19,11 @@ export class OneBot11WsEndpoint {
|
|
|
19
19
|
#open = false;
|
|
20
20
|
#unregisterAgent;
|
|
21
21
|
constructor(options) {
|
|
22
|
+
this.#logger = getAdapterLogger('onebot11', options.config.id);
|
|
22
23
|
this.#options = options;
|
|
23
24
|
const { config } = options;
|
|
24
25
|
this.#lifecycle = createEndpointLifecycle({
|
|
25
|
-
name: config.
|
|
26
|
+
name: config.id,
|
|
26
27
|
reconnect: {
|
|
27
28
|
initialIntervalMs: config.reconnect_interval,
|
|
28
29
|
// 固定间隔(multiplier 1、无抖动),对齐旧 reconnect_interval 语义
|
|
@@ -37,7 +38,7 @@ export class OneBot11WsEndpoint {
|
|
|
37
38
|
if (this.#lifecycle.started)
|
|
38
39
|
return;
|
|
39
40
|
// agent 注册/反注册是适配器专有依赖,留在适配器侧(见 endpoint-lifecycle 迁移指引)
|
|
40
|
-
this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.
|
|
41
|
+
this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.id, this);
|
|
41
42
|
try {
|
|
42
43
|
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
43
44
|
}
|
|
@@ -72,15 +73,15 @@ export class OneBot11WsEndpoint {
|
|
|
72
73
|
rejectAllPending(this.#pending);
|
|
73
74
|
this.#ws = undefined;
|
|
74
75
|
}
|
|
75
|
-
async send({
|
|
76
|
+
async send({ conversation, payload }) {
|
|
76
77
|
const message = formatOutboundSegments(payload);
|
|
77
|
-
const { action, params } = buildSendAction(
|
|
78
|
+
const { action, params } = buildSendAction(conversation, message);
|
|
78
79
|
const data = await this.callApi(action, params);
|
|
79
80
|
const messageId = data?.message_id != null ? String(data.message_id) : '';
|
|
80
|
-
logger.debug(formatCompact({
|
|
81
|
+
this.#logger.debug(formatCompact({
|
|
81
82
|
op: 'onebot11_send',
|
|
82
|
-
endpoint: this.#options.config.
|
|
83
|
-
target
|
|
83
|
+
endpoint: this.#options.config.id,
|
|
84
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
84
85
|
messageId,
|
|
85
86
|
}));
|
|
86
87
|
return messageId;
|
|
@@ -107,19 +108,26 @@ export class OneBot11WsEndpoint {
|
|
|
107
108
|
admit(ev) {
|
|
108
109
|
if (!this.#open || !isMessageEvent(ev))
|
|
109
110
|
return;
|
|
110
|
-
const
|
|
111
|
+
const conversation = onebot11InboundConversation(String(this.#options.id), ev);
|
|
111
112
|
const content = formatInboundContent(ev);
|
|
113
|
+
const inbound = formatInboundMetadata(ev, this.#options.config.id);
|
|
112
114
|
void this.#options.gateway.receive({
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
conversation,
|
|
116
|
+
message: { conversation, id: String(ev.message_id) },
|
|
115
117
|
content,
|
|
116
|
-
sender:
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
sender: {
|
|
119
|
+
id: senderUserId(ev),
|
|
120
|
+
name: senderDisplayName(ev) || undefined,
|
|
121
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
122
|
+
},
|
|
123
|
+
endpointId: inbound.endpointId,
|
|
124
|
+
...(inbound.mentioned ? { mentioned: true } : {}),
|
|
125
|
+
...(inbound.replyTo ? { replyTo: inbound.replyTo } : {}),
|
|
126
|
+
metadata: inbound.metadata,
|
|
119
127
|
}).catch((err) => {
|
|
120
|
-
logger.warn(formatCompact({
|
|
128
|
+
this.#logger.warn(formatCompact({
|
|
121
129
|
op: 'onebot11_gateway_receive_failed',
|
|
122
|
-
target
|
|
130
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
123
131
|
error: err instanceof Error ? err.message : String(err),
|
|
124
132
|
}));
|
|
125
133
|
});
|
|
@@ -145,14 +153,14 @@ export class OneBot11WsEndpoint {
|
|
|
145
153
|
return;
|
|
146
154
|
settled = true;
|
|
147
155
|
if (!this.#options.config.access_token) {
|
|
148
|
-
logger.warn(formatCompact({
|
|
149
|
-
endpoint: this.#options.config.
|
|
156
|
+
this.#logger.warn(formatCompact({
|
|
157
|
+
endpoint: this.#options.config.id,
|
|
150
158
|
ok: false,
|
|
151
159
|
error: 'missing access_token',
|
|
152
160
|
}));
|
|
153
161
|
}
|
|
154
|
-
logger.debug(formatCompact({
|
|
155
|
-
endpoint: this.#options.config.
|
|
162
|
+
this.#logger.debug(formatCompact({
|
|
163
|
+
endpoint: this.#options.config.id,
|
|
156
164
|
mode: 'ws',
|
|
157
165
|
url: safeUrl,
|
|
158
166
|
}));
|
|
@@ -161,7 +169,7 @@ export class OneBot11WsEndpoint {
|
|
|
161
169
|
});
|
|
162
170
|
ws.on('message', (data) => {
|
|
163
171
|
handleOneBot11WsMessage(data, {
|
|
164
|
-
|
|
172
|
+
endpointId: this.#options.config.id,
|
|
165
173
|
pending: this.#pending,
|
|
166
174
|
admit: (ev) => this.admit(ev),
|
|
167
175
|
});
|
|
@@ -188,9 +196,9 @@ export class OneBot11WsEndpoint {
|
|
|
188
196
|
});
|
|
189
197
|
ws.on('error', (err) => {
|
|
190
198
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
191
|
-
logger.warn(formatCompact({
|
|
199
|
+
this.#logger.warn(formatCompact({
|
|
192
200
|
op: 'ws_error',
|
|
193
|
-
endpoint: this.#options.config.
|
|
201
|
+
endpoint: this.#options.config.id,
|
|
194
202
|
ok: false,
|
|
195
203
|
error: error.message,
|
|
196
204
|
}));
|
package/lib/ws-transport.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type OneBot11Event } from './protocol.js';
|
|
|
2
2
|
import { type OneBot11PendingAction, type OneBot11WsSocket } from './ws-types.js';
|
|
3
3
|
export declare function decodeWsPayload(data: unknown): string;
|
|
4
4
|
export declare function handleOneBot11WsMessage(data: unknown, options: {
|
|
5
|
-
readonly
|
|
5
|
+
readonly endpointId: string;
|
|
6
6
|
readonly pending: Map<string, OneBot11PendingAction>;
|
|
7
7
|
readonly admit: (ev: OneBot11Event) => void;
|
|
8
8
|
}): void;
|
package/lib/ws-transport.js
CHANGED
|
@@ -33,7 +33,7 @@ export function handleOneBot11WsMessage(data, options) {
|
|
|
33
33
|
catch (error) {
|
|
34
34
|
logger.warn(formatCompact({
|
|
35
35
|
op: 'onebot11_parse_failed',
|
|
36
|
-
endpoint: options.
|
|
36
|
+
endpoint: options.endpointId,
|
|
37
37
|
error: error instanceof Error ? error.message : String(error),
|
|
38
38
|
}));
|
|
39
39
|
}
|
package/lib/wss-endpoint.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EndpointInstance, EndpointManagement } from '@zhin.js/adapter';
|
|
1
|
+
import type { EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
|
|
2
2
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
3
3
|
import type { HttpHost } from '@zhin.js/host-http';
|
|
4
4
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
@@ -17,10 +17,7 @@ export declare class OneBot11WssEndpoint implements EndpointInstance {
|
|
|
17
17
|
open(): void;
|
|
18
18
|
close(): void;
|
|
19
19
|
stop(): Promise<void>;
|
|
20
|
-
send({
|
|
21
|
-
readonly target: string;
|
|
22
|
-
readonly payload: unknown;
|
|
23
|
-
}): Promise<string>;
|
|
20
|
+
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
24
21
|
recallMessage(messageId: string): Promise<void>;
|
|
25
22
|
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
26
23
|
setTitle(groupId: number, userId: number, title: string, duration?: number): Promise<boolean>;
|