@zhin.js/adapter-onebot11 1.1.17 → 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 +66 -0
- package/README.md +22 -5
- package/adapters/onebot11/index.js +3 -26
- package/adapters/onebot11/index.ts +2 -32
- package/commands/onebot11/endpoint/definition.js +0 -2
- package/commands/onebot11/endpoint/definition.ts +0 -2
- package/lib/adapter.d.ts +20 -0
- package/lib/adapter.js +26 -0
- package/lib/client.d.ts +13 -11
- package/lib/client.js +35 -12
- package/lib/console-spec.d.ts +12 -0
- package/lib/console-spec.js +12 -0
- package/lib/console.d.ts +8 -0
- package/lib/console.js +13 -0
- package/lib/content-port.d.ts +2 -2
- package/lib/content-port.js +2 -2
- package/lib/endpoint-management.d.ts +2 -2
- package/lib/endpoint-management.js +8 -8
- package/lib/identity.d.ts +3 -0
- package/lib/identity.js +32 -0
- package/lib/index.d.ts +3 -2
- package/lib/index.js +3 -2
- package/lib/self-id.js +1 -1
- package/lib/side-event-dispatch.d.ts +8 -1
- package/lib/side-event-dispatch.js +2 -1
- package/lib/ws-endpoint.d.ts +5 -12
- package/lib/ws-endpoint.js +75 -50
- package/lib/ws-transport.d.ts +18 -11
- package/lib/ws-transport.js +28 -56
- package/lib/ws-types.d.ts +0 -6
- package/lib/wss-endpoint.d.ts +5 -12
- package/lib/wss-endpoint.js +76 -53
- package/package.json +25 -17
- package/pages/index/index.js +15 -0
- package/pages/index/index.ts +16 -0
- package/plugin.js +3 -4
- package/src/adapter.ts +32 -0
- package/src/client.ts +38 -28
- package/src/console-spec.ts +17 -0
- package/src/console.ts +18 -0
- package/src/content-port.ts +4 -4
- package/src/endpoint-management.ts +15 -12
- package/src/identity.ts +30 -0
- package/src/index.ts +4 -4
- package/src/self-id.ts +1 -1
- package/src/side-event-dispatch.ts +9 -7
- package/src/ws-endpoint.ts +71 -64
- package/src/ws-transport.ts +41 -82
- package/src/ws-types.ts +0 -7
- package/src/wss-endpoint.ts +73 -68
- package/lib/onebot11-runtime-state.d.ts +0 -1
- package/lib/onebot11-runtime-state.js +0 -6
- package/src/onebot11-runtime-state.ts +0 -7
|
@@ -4,4 +4,11 @@ import type { OneBot11Event } from './protocol.js';
|
|
|
4
4
|
export interface OneBot11SideEventCaller {
|
|
5
5
|
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
/** Exact instance-owned dependencies for one canonical side-event projection. */
|
|
8
|
+
export interface OneBot11SideEventContext {
|
|
9
|
+
readonly emit: EndpointEventEmitter;
|
|
10
|
+
readonly endpointKey: string;
|
|
11
|
+
readonly caller: OneBot11SideEventCaller;
|
|
12
|
+
readonly logger: ReturnType<typeof getAdapterLogger>;
|
|
13
|
+
}
|
|
14
|
+
export declare function receiveOneBot11SideEvent(raw: OneBot11Event, context: OneBot11SideEventContext): void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { receiveOneBotLikeSideEvent } from '@zhin.js/core';
|
|
2
2
|
import { formatCompact } from '@zhin.js/logger';
|
|
3
|
-
export function receiveOneBot11SideEvent(
|
|
3
|
+
export function receiveOneBot11SideEvent(raw, context) {
|
|
4
|
+
const { emit, endpointKey, caller, logger } = context;
|
|
4
5
|
if (!emit)
|
|
5
6
|
return;
|
|
6
7
|
const record = raw;
|
package/lib/ws-endpoint.d.ts
CHANGED
|
@@ -1,25 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { endpointSpec, type Endpoint, type EndpointSpecification } from 'zhin.js/adapter';
|
|
2
2
|
import type { CapabilityId } from 'zhin.js';
|
|
3
3
|
import { type OneBot11WsConfig } from './protocol.js';
|
|
4
4
|
import { type OneBot11WsCreateOptions, type OneBot11WsSocket } from './ws-types.js';
|
|
5
|
-
import {
|
|
5
|
+
import { Onebot11Client } from './client.js';
|
|
6
6
|
export interface OneBot11WsEndpointOptions {
|
|
7
|
+
readonly signal?: AbortSignal;
|
|
7
8
|
readonly id: CapabilityId;
|
|
8
9
|
/** 连接后 best-effort 调用 get_login_info 上报账号(Adapter 工厂开启;默认关闭以免占用首个 echo)。 */
|
|
9
10
|
readonly probeLoginInfo?: boolean;
|
|
10
11
|
readonly config: OneBot11WsConfig;
|
|
11
12
|
readonly createWebSocket?: (url: string, options: OneBot11WsCreateOptions) => OneBot11WsSocket;
|
|
12
13
|
}
|
|
13
|
-
export declare class OneBot11WsEndpoint extends
|
|
14
|
+
export declare class OneBot11WsEndpoint extends Onebot11Client implements Endpoint {
|
|
14
15
|
#private;
|
|
15
|
-
readonly
|
|
16
|
-
readonly management: EndpointManagement;
|
|
17
|
-
readonly control: EndpointControl;
|
|
18
|
-
readonly content: import("@zhin.js/adapter").EndpointContentPort;
|
|
16
|
+
readonly [endpointSpec]: EndpointSpecification;
|
|
19
17
|
constructor(options: OneBot11WsEndpointOptions);
|
|
20
|
-
get transportState(): EndpointTransportState;
|
|
21
|
-
start(): Promise<void>;
|
|
22
|
-
stop(): Promise<void>;
|
|
23
|
-
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
24
|
-
recallMessage(messageId: string): Promise<void>;
|
|
25
18
|
}
|
package/lib/ws-endpoint.js
CHANGED
|
@@ -3,39 +3,59 @@ import { EndpointDeliveryError } from '@zhin.js/im-contract';
|
|
|
3
3
|
* OneBot11 WS client endpoint — outbound connect to OneBot implementation.
|
|
4
4
|
*/
|
|
5
5
|
import WebSocket from 'ws';
|
|
6
|
-
import {
|
|
6
|
+
import { createEndpointSpecification, endpointSpec, createRecallEndpointControl, createEndpointLifecycle, } from 'zhin.js/adapter';
|
|
7
7
|
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
8
8
|
import { createOneBot11EndpointManagement } from './endpoint-management.js';
|
|
9
9
|
import { buildSendAction, buildWsConnectOptions, formatInboundContent, formatInboundMetadata, formatOutboundSegments, isMessageEvent, onebot11InboundConversation, senderDisplayName, senderUserId, } from './protocol.js';
|
|
10
10
|
import { receiveOneBot11SideEvent } from './side-event-dispatch.js';
|
|
11
11
|
import { createOneBot11ContentPort } from './content-port.js';
|
|
12
|
-
import {
|
|
12
|
+
import { createOneBot11Rpc } from './ws-transport.js';
|
|
13
13
|
import { probeOnebot11SelfId, resolveOnebot11SelfId } from './self-id.js';
|
|
14
|
-
import { callOnebot11Client,
|
|
15
|
-
export class OneBot11WsEndpoint extends
|
|
16
|
-
|
|
14
|
+
import { callOnebot11Client, readOnebot11Response, onebot11ClientOptions, forwardOnebot11ClientEvents, Onebot11Client } from './client.js';
|
|
15
|
+
export class OneBot11WsEndpoint extends Onebot11Client {
|
|
16
|
+
[endpointSpec];
|
|
17
|
+
#open = false;
|
|
17
18
|
#logger;
|
|
18
19
|
#options;
|
|
19
|
-
management;
|
|
20
|
-
control = createRecallEndpointControl((id) => this
|
|
21
|
-
content;
|
|
20
|
+
#management;
|
|
21
|
+
#control = createRecallEndpointControl((id, signal) => this.#recallMessage(id, signal));
|
|
22
|
+
#content;
|
|
23
|
+
#releaseClientEvents;
|
|
22
24
|
#lifecycle;
|
|
23
25
|
#ws;
|
|
24
26
|
#stopped = false;
|
|
25
|
-
#
|
|
26
|
-
#pending = new Map();
|
|
27
|
+
#rpc;
|
|
27
28
|
constructor(options) {
|
|
28
|
-
|
|
29
|
+
const rpc = createOneBot11Rpc({ endpointId: options.config.id, signal: options.signal,
|
|
30
|
+
socket: () => this.#lifecycle.state === 'open' ? this.#ws : undefined,
|
|
31
|
+
});
|
|
32
|
+
super(onebot11ClientOptions(options.config, (action, params) => rpc.call({ action, params })));
|
|
33
|
+
this.#rpc = rpc;
|
|
29
34
|
this.#logger = getAdapterLogger('onebot11', options.config.id);
|
|
30
35
|
this.#options = options;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this
|
|
34
|
-
|
|
35
|
-
this
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const callApi = (request) => this.#rpc.call(request).then(readOnebot11Response);
|
|
37
|
+
this.#management = createOneBot11EndpointManagement({ callApi });
|
|
38
|
+
this.#content = createOneBot11ContentPort(callApi);
|
|
39
|
+
const readTransportState = () => this.#lifecycle.state;
|
|
40
|
+
this[endpointSpec] = createEndpointSpecification(this, {
|
|
41
|
+
name: options.config.id,
|
|
42
|
+
start: () => this.#start(), open: () => { this.#open = true; },
|
|
43
|
+
close: () => { this.#open = false; }, stop: () => this.#stop(),
|
|
44
|
+
send: request => this.#send(request),
|
|
45
|
+
get transportState() { return readTransportState(); },
|
|
46
|
+
management: this.#management, control: this.#control, content: this.#content,
|
|
47
|
+
});
|
|
48
|
+
this.#releaseClientEvents = forwardOnebot11ClientEvents(this, (name, payload) => {
|
|
49
|
+
void this[endpointSpec].events.run(() => {
|
|
50
|
+
// A native frame can arrive before start resolves. The spec owns candidate
|
|
51
|
+
// buffering and Root/child admission; transport start is not publication.
|
|
52
|
+
if (this.#stopped || (!this.#open && !this.#lifecycle.started))
|
|
53
|
+
return;
|
|
54
|
+
void this[endpointSpec].events.platform(name, payload).catch(error => this.#warnPlatformEvent(error));
|
|
55
|
+
if (name === 'event')
|
|
56
|
+
this.#admitRaw(payload);
|
|
57
|
+
}).catch(error => this.#warnPlatformEvent(error));
|
|
58
|
+
});
|
|
39
59
|
const { config } = options;
|
|
40
60
|
this.#lifecycle = createEndpointLifecycle({
|
|
41
61
|
name: config.id,
|
|
@@ -49,10 +69,10 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
49
69
|
heartbeat: { intervalMs: config.heartbeat_interval, watchdogMisses: 2 },
|
|
50
70
|
});
|
|
51
71
|
}
|
|
52
|
-
get transportState() {
|
|
72
|
+
get #transportState() {
|
|
53
73
|
return this.#lifecycle.state;
|
|
54
74
|
}
|
|
55
|
-
async start() {
|
|
75
|
+
async #start() {
|
|
56
76
|
if (this.#lifecycle.started)
|
|
57
77
|
return;
|
|
58
78
|
this.#stopped = false;
|
|
@@ -75,19 +95,24 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
75
95
|
throw err;
|
|
76
96
|
}
|
|
77
97
|
}
|
|
78
|
-
async stop() {
|
|
98
|
+
async #stop() {
|
|
79
99
|
this.#stopped = true;
|
|
80
|
-
this
|
|
100
|
+
this.#open = false;
|
|
81
101
|
// 基座负责:清重连/心跳定时器、强关 ws、唤醒 stop-during-connect 竞态
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
102
|
+
try {
|
|
103
|
+
await this.#lifecycle.stop();
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
this.#rpc.dispose();
|
|
107
|
+
this.#releaseClientEvents();
|
|
108
|
+
this.#ws = undefined;
|
|
109
|
+
this[endpointSpec].reportSelfUserId(undefined);
|
|
110
|
+
}
|
|
86
111
|
}
|
|
87
|
-
async send({ conversation, payload }) {
|
|
112
|
+
async #send({ conversation, payload, signal }) {
|
|
88
113
|
const message = formatOutboundSegments(payload);
|
|
89
114
|
const { action, params } = buildSendAction(conversation, message);
|
|
90
|
-
const data = await
|
|
115
|
+
const data = readOnebot11Response(await this.#rpc.call({ action, params, signal }));
|
|
91
116
|
const rawId = data?.message_id;
|
|
92
117
|
if ((typeof rawId !== 'number' && typeof rawId !== 'string') || String(rawId).trim() === '' || (typeof rawId === 'number' && !Number.isFinite(rawId))) {
|
|
93
118
|
throw new EndpointDeliveryError('delivery_unconfirmed', 'Message delivery is unconfirmed: platform returned no message_id', 'unknown');
|
|
@@ -101,26 +126,30 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
101
126
|
}));
|
|
102
127
|
return messageId;
|
|
103
128
|
}
|
|
104
|
-
async recallMessage(messageId) {
|
|
129
|
+
async #recallMessage(messageId, signal) {
|
|
105
130
|
if (!messageId)
|
|
106
131
|
return;
|
|
107
|
-
await
|
|
108
|
-
}
|
|
109
|
-
#callApi(action, params = {}) {
|
|
110
|
-
return callOneBot11WsAction(this.#lifecycle.state === 'open' ? this.#ws : undefined, this.#pending, this.#requestId, action, params);
|
|
132
|
+
await this.#rpc.call({ action: 'delete_msg', params: { message_id: Number(messageId) }, signal }).then(readOnebot11Response);
|
|
111
133
|
}
|
|
112
134
|
#admitRaw(ev) {
|
|
113
135
|
const selfId = resolveOnebot11SelfId(ev.self_id);
|
|
114
|
-
if (!this.#stopped && selfId
|
|
115
|
-
this.reportSelfUserId(selfId);
|
|
136
|
+
if (!this.#stopped && selfId)
|
|
137
|
+
this[endpointSpec].reportSelfUserId(selfId);
|
|
116
138
|
if (!isMessageEvent(ev)) {
|
|
117
|
-
receiveOneBot11SideEvent(
|
|
139
|
+
receiveOneBot11SideEvent(ev, {
|
|
140
|
+
emit: (name, payload) => this[endpointSpec].events.emit(name, payload),
|
|
141
|
+
endpointKey: this.#options.config.id,
|
|
142
|
+
caller: { callApi: (action, params) => callOnebot11Client({ client: this, action, params }) },
|
|
143
|
+
logger: this.#logger,
|
|
144
|
+
});
|
|
118
145
|
return;
|
|
119
146
|
}
|
|
120
|
-
const conversation = onebot11InboundConversation(String(this.#options.id), ev);
|
|
147
|
+
const conversation = { ...onebot11InboundConversation(String(this.#options.id), ev), endpoint: this[endpointSpec].identity };
|
|
121
148
|
const content = formatInboundContent(ev);
|
|
122
149
|
const inbound = formatInboundMetadata(ev, this.#options.config.id);
|
|
123
|
-
void this.
|
|
150
|
+
void this[endpointSpec].events.message({
|
|
151
|
+
event: ev,
|
|
152
|
+
...(typeof ev.time === 'number' ? { platformSentAt: ev.time * 1000 } : {}),
|
|
124
153
|
conversation,
|
|
125
154
|
message: { conversation, id: String(ev.message_id) },
|
|
126
155
|
content,
|
|
@@ -143,16 +172,16 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
143
172
|
}
|
|
144
173
|
/** Best-effort 登录账号探测;失败仅 debug,不影响连接。 */
|
|
145
174
|
async #probeSelfUserId() {
|
|
146
|
-
const selfId = await probeOnebot11SelfId(this
|
|
175
|
+
const selfId = await probeOnebot11SelfId(this, (error) => {
|
|
147
176
|
this.#logger.debug(formatCompact({
|
|
148
177
|
op: 'onebot11_get_login_info_failed',
|
|
149
178
|
error: error instanceof Error ? error.message : String(error),
|
|
150
179
|
}));
|
|
151
180
|
});
|
|
152
|
-
if (this.#stopped || this
|
|
181
|
+
if (this.#stopped || this.#transportState !== 'open')
|
|
153
182
|
return;
|
|
154
|
-
if (selfId
|
|
155
|
-
this.reportSelfUserId(selfId);
|
|
183
|
+
if (selfId)
|
|
184
|
+
this[endpointSpec].reportSelfUserId(selfId);
|
|
156
185
|
}
|
|
157
186
|
#warnPlatformEvent(error) {
|
|
158
187
|
this.#logger.warn(formatCompact({
|
|
@@ -170,7 +199,7 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
170
199
|
this.#ws = ws;
|
|
171
200
|
handle.onForceClose(() => {
|
|
172
201
|
if (this.#ws === ws) {
|
|
173
|
-
|
|
202
|
+
this.#rpc.disconnect();
|
|
174
203
|
}
|
|
175
204
|
try {
|
|
176
205
|
ws.close();
|
|
@@ -206,17 +235,13 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
206
235
|
if (this.#ws !== ws || ws.readyState !== 1 || !this.#lifecycle.started)
|
|
207
236
|
return;
|
|
208
237
|
this.#lifecycle.notifyHeartbeatAck();
|
|
209
|
-
|
|
210
|
-
endpointId: this.#options.config.id,
|
|
211
|
-
pending: this.#pending,
|
|
212
|
-
ingest: (ev) => this.client.ingest(ev),
|
|
213
|
-
});
|
|
238
|
+
this.#rpc.receive(data, (ev) => this.ingest(ev));
|
|
214
239
|
});
|
|
215
240
|
ws.on('close', (code, reason) => {
|
|
216
241
|
if (this.#ws !== ws)
|
|
217
242
|
return;
|
|
218
243
|
this.#ws = undefined;
|
|
219
|
-
|
|
244
|
+
this.#rpc.disconnect();
|
|
220
245
|
const reasonStr = typeof reason === 'string'
|
|
221
246
|
? reason
|
|
222
247
|
: Buffer.isBuffer(reason)
|
package/lib/ws-transport.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export
|
|
1
|
+
import { type PendingRpc, type PendingRpcRequest } from 'zhin.js/adapter';
|
|
2
|
+
import type { OneBot11ActionResponse, OneBot11Event } from './protocol.js';
|
|
3
|
+
import { type OneBot11WsSocket } from './ws-types.js';
|
|
4
|
+
export interface OneBot11RpcOptions {
|
|
5
5
|
readonly endpointId: string;
|
|
6
|
-
readonly
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
readonly signal?: AbortSignal;
|
|
7
|
+
/** Reads the lifecycle's selected socket; RPC never opens or reconnects it. */
|
|
8
|
+
readonly socket: () => OneBot11WsSocket | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface OneBot11Rpc {
|
|
11
|
+
call(request: PendingRpcRequest): Promise<OneBot11ActionResponse>;
|
|
12
|
+
receive(data: unknown, ingest: (event: OneBot11Event) => void): void;
|
|
13
|
+
disconnect: PendingRpc<OneBot11ActionResponse>['disconnect'];
|
|
14
|
+
dispose(): void;
|
|
15
|
+
readonly pendingCount: number;
|
|
16
|
+
}
|
|
17
|
+
/** A Client's one request owner serves native SDK actions and framework operations. */
|
|
18
|
+
export declare function createOneBot11Rpc(options: OneBot11RpcOptions): OneBot11Rpc;
|
|
19
|
+
export declare function decodeWsPayload(data: unknown): string;
|
package/lib/ws-transport.js
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { clearTimeout, setTimeout } from 'node:timers';
|
|
1
|
+
import { createPendingRpc } from 'zhin.js/adapter';
|
|
3
2
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
4
|
-
import { WS_OPEN
|
|
3
|
+
import { WS_OPEN } from './ws-types.js';
|
|
5
4
|
const logger = getLogger('onebot11');
|
|
5
|
+
/** A Client's one request owner serves native SDK actions and framework operations. */
|
|
6
|
+
export function createOneBot11Rpc(options) {
|
|
7
|
+
const pending = createPendingRpc({
|
|
8
|
+
signal: options.signal, requestPrefix: 'ob11_', timeoutMs: 30_000,
|
|
9
|
+
transport: () => { const socket = options.socket(); return socket?.readyState === WS_OPEN ? socket : undefined; },
|
|
10
|
+
serialize: request => JSON.stringify({ action: request.action, params: request.params ?? {}, echo: request.id }),
|
|
11
|
+
});
|
|
12
|
+
return Object.freeze({
|
|
13
|
+
call: pending.call, disconnect: pending.disconnect, dispose: pending.dispose,
|
|
14
|
+
get pendingCount() { return pending.pendingCount; },
|
|
15
|
+
receive(data, ingest) {
|
|
16
|
+
try {
|
|
17
|
+
const message = JSON.parse(decodeWsPayload(data));
|
|
18
|
+
if ('echo' in message && typeof message.echo === 'string') {
|
|
19
|
+
pending.accept({ id: message.echo, value: message });
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
ingest(message);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
logger.warn(formatCompact({ op: 'onebot11_parse_failed', endpoint: options.endpointId,
|
|
26
|
+
error: error instanceof Error ? error.message : String(error) }));
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
6
31
|
export function decodeWsPayload(data) {
|
|
7
32
|
if (typeof data === 'string')
|
|
8
33
|
return data;
|
|
@@ -12,56 +37,3 @@ export function decodeWsPayload(data) {
|
|
|
12
37
|
return new TextDecoder().decode(data);
|
|
13
38
|
return String(data ?? '');
|
|
14
39
|
}
|
|
15
|
-
export function handleOneBot11WsMessage(data, options) {
|
|
16
|
-
try {
|
|
17
|
-
const raw = decodeWsPayload(data);
|
|
18
|
-
const msg = JSON.parse(raw);
|
|
19
|
-
if ('echo' in msg && typeof msg.echo === 'string') {
|
|
20
|
-
const resp = msg;
|
|
21
|
-
const pending = options.pending.get(resp.echo);
|
|
22
|
-
if (pending) {
|
|
23
|
-
options.pending.delete(resp.echo);
|
|
24
|
-
clearTimeout(pending.timeout);
|
|
25
|
-
pending.resolve(resp);
|
|
26
|
-
}
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
options.ingest(msg);
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
logger.warn(formatCompact({
|
|
33
|
-
op: 'onebot11_parse_failed',
|
|
34
|
-
endpoint: options.endpointId,
|
|
35
|
-
error: error instanceof Error ? error.message : String(error),
|
|
36
|
-
}));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
export function callOneBot11WsAction(ws, pending, requestId, action, params) {
|
|
40
|
-
if (!ws || ws.readyState !== WS_OPEN) {
|
|
41
|
-
return Promise.reject(new EndpointDeliveryError('endpoint_disconnected', 'WebSocket 未连接', 'not_sent'));
|
|
42
|
-
}
|
|
43
|
-
const echo = `ob11_${++requestId.value}`;
|
|
44
|
-
const req = { action, params, echo };
|
|
45
|
-
return new Promise((resolve, reject) => {
|
|
46
|
-
const timeout = setTimeout(() => {
|
|
47
|
-
pending.delete(echo);
|
|
48
|
-
reject(new EndpointDeliveryError('endpoint_timeout', `OneBot11 动作超时: ${action}`, 'unknown'));
|
|
49
|
-
}, 30_000);
|
|
50
|
-
pending.set(echo, { resolve, reject, timeout });
|
|
51
|
-
try {
|
|
52
|
-
ws.send(JSON.stringify(req));
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
pending.delete(echo);
|
|
56
|
-
clearTimeout(timeout);
|
|
57
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
export function rejectAllPending(pending, message = '连接已关闭') {
|
|
62
|
-
for (const [, entry] of pending) {
|
|
63
|
-
clearTimeout(entry.timeout);
|
|
64
|
-
entry.reject(new EndpointDeliveryError('endpoint_disconnected', message, 'unknown'));
|
|
65
|
-
}
|
|
66
|
-
pending.clear();
|
|
67
|
-
}
|
package/lib/ws-types.d.ts
CHANGED
|
@@ -10,9 +10,3 @@ export interface OneBot11WsCreateOptions {
|
|
|
10
10
|
readonly headers?: Record<string, string>;
|
|
11
11
|
}
|
|
12
12
|
export declare const WS_OPEN = 1;
|
|
13
|
-
export interface OneBot11PendingAction {
|
|
14
|
-
resolve: (value: OneBot11ActionResponse) => void;
|
|
15
|
-
reject: (err: Error) => void;
|
|
16
|
-
timeout: NodeJS.Timeout;
|
|
17
|
-
}
|
|
18
|
-
import type { OneBot11ActionResponse } from './protocol.js';
|
package/lib/wss-endpoint.d.ts
CHANGED
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OneBot11 reverse WSS endpoint — accepts inbound WebSocket from OneBot implementation.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { endpointSpec, type Endpoint, type EndpointSpecification } from 'zhin.js/adapter';
|
|
5
5
|
import type { HttpHost } from '@zhin.js/host-http';
|
|
6
6
|
import type { CapabilityId } from 'zhin.js';
|
|
7
7
|
import { type OneBot11WssConfig } from './protocol.js';
|
|
8
|
-
import {
|
|
8
|
+
import { Onebot11Client } from './client.js';
|
|
9
9
|
export interface OneBot11WssEndpointOptions {
|
|
10
|
+
readonly signal?: AbortSignal;
|
|
10
11
|
readonly id: CapabilityId;
|
|
11
12
|
/** 连接后 best-effort 调用 get_login_info 上报账号(Adapter 工厂开启)。 */
|
|
12
13
|
readonly probeLoginInfo?: boolean;
|
|
13
14
|
readonly http: HttpHost;
|
|
14
15
|
readonly config: OneBot11WssConfig;
|
|
15
16
|
}
|
|
16
|
-
export declare class OneBot11WssEndpoint extends
|
|
17
|
+
export declare class OneBot11WssEndpoint extends Onebot11Client implements Endpoint {
|
|
17
18
|
#private;
|
|
18
|
-
readonly
|
|
19
|
-
readonly management: EndpointManagement;
|
|
20
|
-
readonly control: EndpointControl;
|
|
21
|
-
readonly content: import("@zhin.js/adapter").EndpointContentPort;
|
|
19
|
+
readonly [endpointSpec]: EndpointSpecification;
|
|
22
20
|
constructor(options: OneBot11WssEndpointOptions);
|
|
23
|
-
get transportState(): EndpointTransportState;
|
|
24
|
-
start(): Promise<void>;
|
|
25
|
-
stop(): Promise<void>;
|
|
26
|
-
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
27
|
-
recallMessage(messageId: string): Promise<void>;
|
|
28
21
|
}
|