@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/src/ws-endpoint.ts
CHANGED
|
@@ -8,9 +8,10 @@ import {
|
|
|
8
8
|
type EndpointInstance,
|
|
9
9
|
type EndpointLifecycle,
|
|
10
10
|
type EndpointManagement,
|
|
11
|
+
type EndpointSendRequest,
|
|
11
12
|
} from '@zhin.js/adapter';
|
|
12
13
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
13
|
-
import { formatCompact,
|
|
14
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
14
15
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
15
16
|
import { createOneBot11EndpointManagement } from './endpoint-management.js';
|
|
16
17
|
import { registerOnebot11AgentEndpoint } from './onebot11-agent-deps.js';
|
|
@@ -19,9 +20,10 @@ import {
|
|
|
19
20
|
buildWsConnectOptions,
|
|
20
21
|
formatInboundContent,
|
|
21
22
|
formatInboundMetadata,
|
|
22
|
-
formatInboundTarget,
|
|
23
23
|
formatOutboundSegments,
|
|
24
24
|
isMessageEvent,
|
|
25
|
+
onebot11InboundConversation,
|
|
26
|
+
senderDisplayName,
|
|
25
27
|
senderUserId,
|
|
26
28
|
type OneBot11Event,
|
|
27
29
|
type OneBot11WsConfig,
|
|
@@ -37,8 +39,6 @@ import {
|
|
|
37
39
|
type OneBot11WsSocket,
|
|
38
40
|
} from './ws-types.js';
|
|
39
41
|
|
|
40
|
-
const logger = getLogger('onebot11');
|
|
41
|
-
|
|
42
42
|
export interface OneBot11WsEndpointOptions {
|
|
43
43
|
readonly id: CapabilityId;
|
|
44
44
|
readonly gateway: MessageGateway;
|
|
@@ -50,6 +50,8 @@ export interface OneBot11WsEndpointOptions {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export class OneBot11WsEndpoint implements EndpointInstance {
|
|
53
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
54
|
+
|
|
53
55
|
readonly #options: OneBot11WsEndpointOptions;
|
|
54
56
|
readonly management: EndpointManagement = createOneBot11EndpointManagement(this);
|
|
55
57
|
readonly #lifecycle: EndpointLifecycle;
|
|
@@ -60,10 +62,11 @@ export class OneBot11WsEndpoint implements EndpointInstance {
|
|
|
60
62
|
#unregisterAgent?: () => void;
|
|
61
63
|
|
|
62
64
|
constructor(options: OneBot11WsEndpointOptions) {
|
|
65
|
+
this.#logger = getAdapterLogger('onebot11', options.config.id);
|
|
63
66
|
this.#options = options;
|
|
64
67
|
const { config } = options;
|
|
65
68
|
this.#lifecycle = createEndpointLifecycle({
|
|
66
|
-
name: config.
|
|
69
|
+
name: config.id,
|
|
67
70
|
reconnect: {
|
|
68
71
|
initialIntervalMs: config.reconnect_interval,
|
|
69
72
|
// 固定间隔(multiplier 1、无抖动),对齐旧 reconnect_interval 语义
|
|
@@ -78,7 +81,7 @@ export class OneBot11WsEndpoint implements EndpointInstance {
|
|
|
78
81
|
async start(): Promise<void> {
|
|
79
82
|
if (this.#lifecycle.started) return;
|
|
80
83
|
// agent 注册/反注册是适配器专有依赖,留在适配器侧(见 endpoint-lifecycle 迁移指引)
|
|
81
|
-
this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.
|
|
84
|
+
this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.id, this);
|
|
82
85
|
try {
|
|
83
86
|
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
84
87
|
} catch (err) {
|
|
@@ -115,15 +118,15 @@ export class OneBot11WsEndpoint implements EndpointInstance {
|
|
|
115
118
|
this.#ws = undefined;
|
|
116
119
|
}
|
|
117
120
|
|
|
118
|
-
async send({
|
|
121
|
+
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
119
122
|
const message = formatOutboundSegments(payload);
|
|
120
|
-
const { action, params } = buildSendAction(
|
|
123
|
+
const { action, params } = buildSendAction(conversation, message);
|
|
121
124
|
const data = await this.callApi(action, params) as { message_id?: number | string } | undefined;
|
|
122
125
|
const messageId = data?.message_id != null ? String(data.message_id) : '';
|
|
123
|
-
logger.debug(formatCompact({
|
|
126
|
+
this.#logger.debug(formatCompact({
|
|
124
127
|
op: 'onebot11_send',
|
|
125
|
-
endpoint: this.#options.config.
|
|
126
|
-
target
|
|
128
|
+
endpoint: this.#options.config.id,
|
|
129
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
127
130
|
messageId,
|
|
128
131
|
}));
|
|
129
132
|
return messageId;
|
|
@@ -157,19 +160,26 @@ export class OneBot11WsEndpoint implements EndpointInstance {
|
|
|
157
160
|
/** Test / internal: admit a parsed event when the endpoint is open. */
|
|
158
161
|
admit(ev: OneBot11Event): void {
|
|
159
162
|
if (!this.#open || !isMessageEvent(ev)) return;
|
|
160
|
-
const
|
|
163
|
+
const conversation = onebot11InboundConversation(String(this.#options.id), ev);
|
|
161
164
|
const content = formatInboundContent(ev);
|
|
165
|
+
const inbound = formatInboundMetadata(ev, this.#options.config.id);
|
|
162
166
|
void this.#options.gateway.receive({
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
conversation,
|
|
168
|
+
message: { conversation, id: String(ev.message_id) },
|
|
165
169
|
content,
|
|
166
|
-
sender:
|
|
167
|
-
|
|
168
|
-
|
|
170
|
+
sender: {
|
|
171
|
+
id: senderUserId(ev),
|
|
172
|
+
name: senderDisplayName(ev) || undefined,
|
|
173
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
174
|
+
},
|
|
175
|
+
endpointId: inbound.endpointId,
|
|
176
|
+
...(inbound.mentioned ? { mentioned: true } : {}),
|
|
177
|
+
...(inbound.replyTo ? { replyTo: inbound.replyTo } : {}),
|
|
178
|
+
metadata: inbound.metadata,
|
|
169
179
|
}).catch((err) => {
|
|
170
|
-
logger.warn(formatCompact({
|
|
180
|
+
this.#logger.warn(formatCompact({
|
|
171
181
|
op: 'onebot11_gateway_receive_failed',
|
|
172
|
-
target
|
|
182
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
173
183
|
error: err instanceof Error ? err.message : String(err),
|
|
174
184
|
}));
|
|
175
185
|
});
|
|
@@ -197,14 +207,14 @@ export class OneBot11WsEndpoint implements EndpointInstance {
|
|
|
197
207
|
if (settled) return;
|
|
198
208
|
settled = true;
|
|
199
209
|
if (!this.#options.config.access_token) {
|
|
200
|
-
logger.warn(formatCompact({
|
|
201
|
-
endpoint: this.#options.config.
|
|
210
|
+
this.#logger.warn(formatCompact({
|
|
211
|
+
endpoint: this.#options.config.id,
|
|
202
212
|
ok: false,
|
|
203
213
|
error: 'missing access_token',
|
|
204
214
|
}));
|
|
205
215
|
}
|
|
206
|
-
logger.debug(formatCompact({
|
|
207
|
-
endpoint: this.#options.config.
|
|
216
|
+
this.#logger.debug(formatCompact({
|
|
217
|
+
endpoint: this.#options.config.id,
|
|
208
218
|
mode: 'ws',
|
|
209
219
|
url: safeUrl,
|
|
210
220
|
}));
|
|
@@ -214,7 +224,7 @@ export class OneBot11WsEndpoint implements EndpointInstance {
|
|
|
214
224
|
|
|
215
225
|
ws.on('message', (data) => {
|
|
216
226
|
handleOneBot11WsMessage(data, {
|
|
217
|
-
|
|
227
|
+
endpointId: this.#options.config.id,
|
|
218
228
|
pending: this.#pending,
|
|
219
229
|
admit: (ev) => this.admit(ev),
|
|
220
230
|
});
|
|
@@ -243,9 +253,9 @@ export class OneBot11WsEndpoint implements EndpointInstance {
|
|
|
243
253
|
|
|
244
254
|
ws.on('error', (err) => {
|
|
245
255
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
246
|
-
logger.warn(formatCompact({
|
|
256
|
+
this.#logger.warn(formatCompact({
|
|
247
257
|
op: 'ws_error',
|
|
248
|
-
endpoint: this.#options.config.
|
|
258
|
+
endpoint: this.#options.config.id,
|
|
249
259
|
ok: false,
|
|
250
260
|
error: error.message,
|
|
251
261
|
}));
|
package/src/ws-transport.ts
CHANGED
|
@@ -23,7 +23,7 @@ export function decodeWsPayload(data: unknown): string {
|
|
|
23
23
|
export function handleOneBot11WsMessage(
|
|
24
24
|
data: unknown,
|
|
25
25
|
options: {
|
|
26
|
-
readonly
|
|
26
|
+
readonly endpointId: string;
|
|
27
27
|
readonly pending: Map<string, OneBot11PendingAction>;
|
|
28
28
|
readonly admit: (ev: OneBot11Event) => void;
|
|
29
29
|
},
|
|
@@ -46,7 +46,7 @@ export function handleOneBot11WsMessage(
|
|
|
46
46
|
} catch (error) {
|
|
47
47
|
logger.warn(formatCompact({
|
|
48
48
|
op: 'onebot11_parse_failed',
|
|
49
|
-
endpoint: options.
|
|
49
|
+
endpoint: options.endpointId,
|
|
50
50
|
error: error instanceof Error ? error.message : String(error),
|
|
51
51
|
}));
|
|
52
52
|
}
|
package/src/wss-endpoint.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* OneBot11 reverse WSS endpoint — accepts inbound WebSocket from OneBot implementation.
|
|
3
3
|
*/
|
|
4
4
|
import { clearInterval } from 'node:timers';
|
|
5
|
-
import type { EndpointInstance, EndpointManagement } from '@zhin.js/adapter';
|
|
5
|
+
import type { EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
|
|
6
6
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
7
7
|
import type { HttpHost, WsConnection } from '@zhin.js/host-http';
|
|
8
|
-
import { formatCompact,
|
|
8
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
9
9
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
10
10
|
import { createOneBot11EndpointManagement } from './endpoint-management.js';
|
|
11
11
|
import { registerOnebot11AgentEndpoint } from './onebot11-agent-deps.js';
|
|
@@ -13,9 +13,10 @@ import {
|
|
|
13
13
|
buildSendAction,
|
|
14
14
|
formatInboundContent,
|
|
15
15
|
formatInboundMetadata,
|
|
16
|
-
formatInboundTarget,
|
|
17
16
|
formatOutboundSegments,
|
|
18
17
|
isMessageEvent,
|
|
18
|
+
onebot11InboundConversation,
|
|
19
|
+
senderDisplayName,
|
|
19
20
|
senderUserId,
|
|
20
21
|
type OneBot11Event,
|
|
21
22
|
type OneBot11WssConfig,
|
|
@@ -33,8 +34,6 @@ import {
|
|
|
33
34
|
type OneBot11WsSocket,
|
|
34
35
|
} from './ws-types.js';
|
|
35
36
|
|
|
36
|
-
const logger = getLogger('onebot11');
|
|
37
|
-
|
|
38
37
|
export interface OneBot11WssEndpointOptions {
|
|
39
38
|
readonly id: CapabilityId;
|
|
40
39
|
readonly gateway: MessageGateway;
|
|
@@ -43,6 +42,8 @@ export interface OneBot11WssEndpointOptions {
|
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
export class OneBot11WssEndpoint implements EndpointInstance {
|
|
45
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
46
|
+
|
|
46
47
|
readonly #options: OneBot11WssEndpointOptions;
|
|
47
48
|
readonly management: EndpointManagement = createOneBot11EndpointManagement(this);
|
|
48
49
|
#ws?: OneBot11WsSocket;
|
|
@@ -55,6 +56,7 @@ export class OneBot11WssEndpoint implements EndpointInstance {
|
|
|
55
56
|
#unregisterAgent?: () => void;
|
|
56
57
|
|
|
57
58
|
constructor(options: OneBot11WssEndpointOptions) {
|
|
59
|
+
this.#logger = getAdapterLogger('onebot11', options.config.id);
|
|
58
60
|
this.#options = options;
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -63,24 +65,24 @@ export class OneBot11WssEndpoint implements EndpointInstance {
|
|
|
63
65
|
this.#started = true;
|
|
64
66
|
if (!this.#options.config.access_token) {
|
|
65
67
|
// wss 模式未配 access_token 时任何连接都会被放行(verifyOneBotAccessToken 直接 return true)
|
|
66
|
-
logger.warn(formatCompact({
|
|
67
|
-
endpoint: this.#options.config.
|
|
68
|
+
this.#logger.warn(formatCompact({
|
|
69
|
+
endpoint: this.#options.config.id,
|
|
68
70
|
mode: 'wss',
|
|
69
71
|
ok: false,
|
|
70
72
|
error: 'missing access_token',
|
|
71
73
|
}));
|
|
72
74
|
}
|
|
73
75
|
this.#unregisterAgent = registerOnebot11AgentEndpoint(
|
|
74
|
-
this.#options.config.
|
|
76
|
+
this.#options.config.id,
|
|
75
77
|
this as unknown as OneBot11WsEndpoint,
|
|
76
78
|
);
|
|
77
79
|
const handle = this.#options.http.ws(this.#options.config.path);
|
|
78
80
|
this.#wsRelease = handle.onConnection((connection) => {
|
|
79
81
|
this.#acceptConnection(connection);
|
|
80
82
|
});
|
|
81
|
-
logger.info(formatCompact({
|
|
83
|
+
this.#logger.info(formatCompact({
|
|
82
84
|
op: 'listen',
|
|
83
|
-
endpoint: this.#options.config.
|
|
85
|
+
endpoint: this.#options.config.id,
|
|
84
86
|
mode: 'wss',
|
|
85
87
|
path: this.#options.config.path,
|
|
86
88
|
}));
|
|
@@ -116,9 +118,9 @@ export class OneBot11WssEndpoint implements EndpointInstance {
|
|
|
116
118
|
this.#started = false;
|
|
117
119
|
}
|
|
118
120
|
|
|
119
|
-
async send({
|
|
121
|
+
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
120
122
|
const message = formatOutboundSegments(payload);
|
|
121
|
-
const { action, params } = buildSendAction(
|
|
123
|
+
const { action, params } = buildSendAction(conversation, message);
|
|
122
124
|
const data = await this.callApi(action, params) as { message_id?: number | string } | undefined;
|
|
123
125
|
return data?.message_id != null ? String(data.message_id) : '';
|
|
124
126
|
}
|
|
@@ -144,18 +146,25 @@ export class OneBot11WssEndpoint implements EndpointInstance {
|
|
|
144
146
|
|
|
145
147
|
admit(ev: OneBot11Event): void {
|
|
146
148
|
if (!this.#open || !isMessageEvent(ev)) return;
|
|
147
|
-
const
|
|
149
|
+
const conversation = onebot11InboundConversation(String(this.#options.id), ev);
|
|
150
|
+
const inbound = formatInboundMetadata(ev, this.#options.config.id);
|
|
148
151
|
void this.#options.gateway.receive({
|
|
149
|
-
|
|
150
|
-
|
|
152
|
+
conversation,
|
|
153
|
+
message: { conversation, id: String(ev.message_id) },
|
|
151
154
|
content: formatInboundContent(ev),
|
|
152
|
-
sender:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
sender: {
|
|
156
|
+
id: senderUserId(ev),
|
|
157
|
+
name: senderDisplayName(ev) || undefined,
|
|
158
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
159
|
+
},
|
|
160
|
+
endpointId: inbound.endpointId,
|
|
161
|
+
...(inbound.mentioned ? { mentioned: true } : {}),
|
|
162
|
+
...(inbound.replyTo ? { replyTo: inbound.replyTo } : {}),
|
|
163
|
+
metadata: inbound.metadata,
|
|
155
164
|
}).catch((err) => {
|
|
156
|
-
logger.warn(formatCompact({
|
|
165
|
+
this.#logger.warn(formatCompact({
|
|
157
166
|
op: 'onebot11_gateway_receive_failed',
|
|
158
|
-
target
|
|
167
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
159
168
|
error: err instanceof Error ? err.message : String(err),
|
|
160
169
|
}));
|
|
161
170
|
});
|
|
@@ -182,7 +191,7 @@ export class OneBot11WssEndpoint implements EndpointInstance {
|
|
|
182
191
|
);
|
|
183
192
|
socket.on('message', (data) => {
|
|
184
193
|
handleOneBot11WsMessage(data, {
|
|
185
|
-
|
|
194
|
+
endpointId: this.#options.config.id,
|
|
186
195
|
pending: this.#pending,
|
|
187
196
|
admit: (ev) => this.admit(ev),
|
|
188
197
|
});
|
|
@@ -196,8 +205,8 @@ export class OneBot11WssEndpoint implements EndpointInstance {
|
|
|
196
205
|
}
|
|
197
206
|
}
|
|
198
207
|
});
|
|
199
|
-
logger.debug(formatCompact({
|
|
200
|
-
endpoint: this.#options.config.
|
|
208
|
+
this.#logger.debug(formatCompact({
|
|
209
|
+
endpoint: this.#options.config.id,
|
|
201
210
|
mode: 'wss',
|
|
202
211
|
peer: connection.request.socket.remoteAddress,
|
|
203
212
|
}));
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|