@zhin.js/adapter-onebot11 1.1.6 → 1.1.8
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 +38 -0
- package/adapters/onebot11/index.js +2 -0
- package/adapters/onebot11/index.ts +2 -0
- package/lib/self-id.d.ts +8 -0
- package/lib/self-id.js +25 -0
- package/lib/ws-endpoint.d.ts +2 -0
- package/lib/ws-endpoint.js +23 -0
- package/lib/wss-endpoint.d.ts +2 -0
- package/lib/wss-endpoint.js +20 -0
- package/package.json +15 -15
- package/src/self-id.ts +28 -0
- package/src/ws-endpoint.ts +22 -0
- package/src/wss-endpoint.ts +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @zhin.js/adapter-onebot11
|
|
2
2
|
|
|
3
|
+
## 1.1.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9891e66: Endpoint 新增运行期 `selfUserId` 访问器与受保护的 `reportSelfUserId()`(`EndpointImplementation` 另可声明 `selfUserId`,`EndpointActivationContext` 提供 `reportSelfUserId`),并新增进程级 Peer Registry(`getProcessPeerRegistry()` / `createPeerRegistry()`)。账号仅在 generation active 后登记,回滚 / retire / stop 后移除;`EndpointIdentity` 保持不可变。ICQQ 在 `system.online` 上报 uin;OneBot11 ws/wss 从事件 `self_id` 与 `get_login_info` 上报;Sandbox 以配置的 bot id 作为合成账号。未上报的旧 Endpoint 不进入 Registry(fail closed),不会用配置 id 兜底。OneBot12 / napcat / milky 等其余适配器留待后续。
|
|
8
|
+
|
|
9
|
+
Peer Registry 使用登记序号(新 generation 胜出),旧实例在新实例登记后再次上报不会覆盖新条目;空值或非字符串的读取查询返回未命中而不抛错;OneBot11 在 stop 时清空 `selfUserId`。
|
|
10
|
+
|
|
11
|
+
登记序号在 Endpoint 激活时通过 `PeerRegistry.reserve()` 分配,新实例先上报、旧实例晚到的首次上报不会覆盖新条目。
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [9891e66]
|
|
14
|
+
- Updated dependencies [bf52b40]
|
|
15
|
+
- Updated dependencies [bf52b40]
|
|
16
|
+
- Updated dependencies [bf52b40]
|
|
17
|
+
- Updated dependencies [386150d]
|
|
18
|
+
- Updated dependencies [9891e66]
|
|
19
|
+
- Updated dependencies [9891e66]
|
|
20
|
+
- Updated dependencies [4778587]
|
|
21
|
+
- Updated dependencies [40537e3]
|
|
22
|
+
- Updated dependencies [681abf3]
|
|
23
|
+
- Updated dependencies [9891e66]
|
|
24
|
+
- Updated dependencies [9891e66]
|
|
25
|
+
- @zhin.js/adapter@1.1.18
|
|
26
|
+
- @zhin.js/core@1.1.43
|
|
27
|
+
- @zhin.js/permission@1.1.5
|
|
28
|
+
- @zhin.js/host-http@1.1.5
|
|
29
|
+
- @zhin.js/feature-kit@1.1.4
|
|
30
|
+
- @zhin.js/agent-feature@1.1.5
|
|
31
|
+
- @zhin.js/skill@1.1.5
|
|
32
|
+
- @zhin.js/tool@1.1.5
|
|
33
|
+
|
|
34
|
+
## 1.1.7
|
|
35
|
+
|
|
36
|
+
### Patch Changes
|
|
37
|
+
|
|
38
|
+
- Updated dependencies [5ab6307]
|
|
39
|
+
- @zhin.js/core@1.1.42
|
|
40
|
+
|
|
3
41
|
## 1.1.6
|
|
4
42
|
|
|
5
43
|
### Patch Changes
|
|
@@ -30,11 +30,13 @@ export default defineAdapter({
|
|
|
30
30
|
id: context.id,
|
|
31
31
|
http: context.use(httpHostToken),
|
|
32
32
|
config,
|
|
33
|
+
probeLoginInfo: true,
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
36
|
return new OneBot11WsEndpoint({
|
|
36
37
|
id: context.id,
|
|
37
38
|
config,
|
|
39
|
+
probeLoginInfo: true,
|
|
38
40
|
});
|
|
39
41
|
},
|
|
40
42
|
});
|
|
@@ -43,11 +43,13 @@ export default defineAdapter<OneBot11EndpointConfig>({
|
|
|
43
43
|
id: context.id,
|
|
44
44
|
http: context.use(httpHostToken),
|
|
45
45
|
config,
|
|
46
|
+
probeLoginInfo: true,
|
|
46
47
|
});
|
|
47
48
|
}
|
|
48
49
|
return new OneBot11WsEndpoint({
|
|
49
50
|
id: context.id,
|
|
50
51
|
config,
|
|
52
|
+
probeLoginInfo: true,
|
|
51
53
|
});
|
|
52
54
|
},
|
|
53
55
|
});
|
package/lib/self-id.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Onebot11Client } from './client.js';
|
|
2
|
+
/**
|
|
3
|
+
* 规范化 OneBot11 平台账号 id(`self_id` / `get_login_info.user_id`)。
|
|
4
|
+
* 非法值、空串、0 均视为未知;绝不使用 `config.id`(那是 Endpoint 名,不是平台账号)。
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveOnebot11SelfId(value: unknown): string | undefined;
|
|
7
|
+
/** Best-effort `get_login_info`;失败返回 undefined 并交给调用方 debug,不抛错。 */
|
|
8
|
+
export declare function probeOnebot11SelfId(client: Onebot11Client, onError: (error: unknown) => void): Promise<string | undefined>;
|
package/lib/self-id.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { callOnebot11Client } from './client.js';
|
|
2
|
+
/**
|
|
3
|
+
* 规范化 OneBot11 平台账号 id(`self_id` / `get_login_info.user_id`)。
|
|
4
|
+
* 非法值、空串、0 均视为未知;绝不使用 `config.id`(那是 Endpoint 名,不是平台账号)。
|
|
5
|
+
*/
|
|
6
|
+
export function resolveOnebot11SelfId(value) {
|
|
7
|
+
if (typeof value === 'number') {
|
|
8
|
+
return Number.isSafeInteger(value) && value > 0 ? String(value) : undefined;
|
|
9
|
+
}
|
|
10
|
+
if (typeof value !== 'string')
|
|
11
|
+
return undefined;
|
|
12
|
+
const trimmed = value.trim();
|
|
13
|
+
return trimmed === '' || trimmed === '0' ? undefined : trimmed;
|
|
14
|
+
}
|
|
15
|
+
/** Best-effort `get_login_info`;失败返回 undefined 并交给调用方 debug,不抛错。 */
|
|
16
|
+
export async function probeOnebot11SelfId(client, onError) {
|
|
17
|
+
try {
|
|
18
|
+
const data = await callOnebot11Client(client, 'get_login_info');
|
|
19
|
+
return resolveOnebot11SelfId(data?.user_id);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
onError(error);
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
package/lib/ws-endpoint.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { type OneBot11WsCreateOptions, type OneBot11WsSocket } from './ws-types.
|
|
|
5
5
|
import { type Onebot11Client } from './client.js';
|
|
6
6
|
export interface OneBot11WsEndpointOptions {
|
|
7
7
|
readonly id: CapabilityId;
|
|
8
|
+
/** 连接后 best-effort 调用 get_login_info 上报账号(Adapter 工厂开启;默认关闭以免占用首个 echo)。 */
|
|
9
|
+
readonly probeLoginInfo?: boolean;
|
|
8
10
|
readonly config: OneBot11WsConfig;
|
|
9
11
|
readonly createWebSocket?: (url: string, options: OneBot11WsCreateOptions) => OneBot11WsSocket;
|
|
10
12
|
}
|
package/lib/ws-endpoint.js
CHANGED
|
@@ -10,6 +10,7 @@ import { buildSendAction, buildWsConnectOptions, formatInboundContent, formatInb
|
|
|
10
10
|
import { receiveOneBot11SideEvent } from './side-event-dispatch.js';
|
|
11
11
|
import { createOneBot11ContentPort } from './content-port.js';
|
|
12
12
|
import { callOneBot11WsAction, handleOneBot11WsMessage, rejectAllPending, } from './ws-transport.js';
|
|
13
|
+
import { probeOnebot11SelfId, resolveOnebot11SelfId } from './self-id.js';
|
|
13
14
|
import { callOnebot11Client, createOnebot11EndpointClient, forwardOnebot11ClientEvents } from './client.js';
|
|
14
15
|
export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
15
16
|
client;
|
|
@@ -20,6 +21,7 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
20
21
|
content;
|
|
21
22
|
#lifecycle;
|
|
22
23
|
#ws;
|
|
24
|
+
#stopped = false;
|
|
23
25
|
#requestId = { value: 0 };
|
|
24
26
|
#pending = new Map();
|
|
25
27
|
constructor(options) {
|
|
@@ -53,8 +55,11 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
53
55
|
async start() {
|
|
54
56
|
if (this.#lifecycle.started)
|
|
55
57
|
return;
|
|
58
|
+
this.#stopped = false;
|
|
56
59
|
try {
|
|
57
60
|
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
61
|
+
if (this.#options.probeLoginInfo)
|
|
62
|
+
void this.#probeSelfUserId();
|
|
58
63
|
}
|
|
59
64
|
catch (err) {
|
|
60
65
|
// start 失败必须清理现场(状态复位由基座保证)
|
|
@@ -71,11 +76,13 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
78
|
async stop() {
|
|
79
|
+
this.#stopped = true;
|
|
74
80
|
this.close();
|
|
75
81
|
// 基座负责:清重连/心跳定时器、强关 ws、唤醒 stop-during-connect 竞态
|
|
76
82
|
await this.#lifecycle.stop();
|
|
77
83
|
rejectAllPending(this.#pending);
|
|
78
84
|
this.#ws = undefined;
|
|
85
|
+
this.reportSelfUserId(undefined);
|
|
79
86
|
}
|
|
80
87
|
async send({ conversation, payload }) {
|
|
81
88
|
const message = formatOutboundSegments(payload);
|
|
@@ -103,6 +110,9 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
103
110
|
return callOneBot11WsAction(this.#lifecycle.state === 'open' ? this.#ws : undefined, this.#pending, this.#requestId, action, params);
|
|
104
111
|
}
|
|
105
112
|
#admitRaw(ev) {
|
|
113
|
+
const selfId = resolveOnebot11SelfId(ev.self_id);
|
|
114
|
+
if (!this.#stopped && selfId && selfId !== this.selfUserId)
|
|
115
|
+
this.reportSelfUserId(selfId);
|
|
106
116
|
if (!isMessageEvent(ev)) {
|
|
107
117
|
receiveOneBot11SideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, { callApi: (action, params) => callOnebot11Client(this.client, action, params) }, ev, this.#logger);
|
|
108
118
|
return;
|
|
@@ -131,6 +141,19 @@ export class OneBot11WsEndpoint extends ClientEndpoint {
|
|
|
131
141
|
}));
|
|
132
142
|
});
|
|
133
143
|
}
|
|
144
|
+
/** Best-effort 登录账号探测;失败仅 debug,不影响连接。 */
|
|
145
|
+
async #probeSelfUserId() {
|
|
146
|
+
const selfId = await probeOnebot11SelfId(this.client, (error) => {
|
|
147
|
+
this.#logger.debug(formatCompact({
|
|
148
|
+
op: 'onebot11_get_login_info_failed',
|
|
149
|
+
error: error instanceof Error ? error.message : String(error),
|
|
150
|
+
}));
|
|
151
|
+
});
|
|
152
|
+
if (this.#stopped || this.transportState !== 'open')
|
|
153
|
+
return;
|
|
154
|
+
if (selfId && selfId !== this.selfUserId)
|
|
155
|
+
this.reportSelfUserId(selfId);
|
|
156
|
+
}
|
|
134
157
|
#warnPlatformEvent(error) {
|
|
135
158
|
this.#logger.warn(formatCompact({
|
|
136
159
|
op: 'onebot11_platform_event_failed',
|
package/lib/wss-endpoint.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ import { type OneBot11WssConfig } from './protocol.js';
|
|
|
8
8
|
import { type Onebot11Client } from './client.js';
|
|
9
9
|
export interface OneBot11WssEndpointOptions {
|
|
10
10
|
readonly id: CapabilityId;
|
|
11
|
+
/** 连接后 best-effort 调用 get_login_info 上报账号(Adapter 工厂开启)。 */
|
|
12
|
+
readonly probeLoginInfo?: boolean;
|
|
11
13
|
readonly http: HttpHost;
|
|
12
14
|
readonly config: OneBot11WssConfig;
|
|
13
15
|
}
|
package/lib/wss-endpoint.js
CHANGED
|
@@ -10,6 +10,7 @@ import { receiveOneBot11SideEvent } from './side-event-dispatch.js';
|
|
|
10
10
|
import { createOneBot11ContentPort } from './content-port.js';
|
|
11
11
|
import { verifyOneBotAccessToken } from './wss-auth.js';
|
|
12
12
|
import { callOneBot11WsAction, handleOneBot11WsMessage, rejectAllPending, } from './ws-transport.js';
|
|
13
|
+
import { probeOnebot11SelfId, resolveOnebot11SelfId } from './self-id.js';
|
|
13
14
|
import { callOnebot11Client, createOnebot11EndpointClient, forwardOnebot11ClientEvents } from './client.js';
|
|
14
15
|
export class OneBot11WssEndpoint extends ClientEndpoint {
|
|
15
16
|
client;
|
|
@@ -98,6 +99,7 @@ export class OneBot11WssEndpoint extends ClientEndpoint {
|
|
|
98
99
|
rejectAllPending(this.#pending);
|
|
99
100
|
this.#ws = undefined;
|
|
100
101
|
this.#started = false;
|
|
102
|
+
this.reportSelfUserId(undefined);
|
|
101
103
|
}
|
|
102
104
|
async send({ conversation, payload }) {
|
|
103
105
|
const message = formatOutboundSegments(payload);
|
|
@@ -118,6 +120,9 @@ export class OneBot11WssEndpoint extends ClientEndpoint {
|
|
|
118
120
|
return callOneBot11WsAction(this.#connectionLifecycle.state === 'closed' ? undefined : this.#ws, this.#pending, this.#requestId, action, params);
|
|
119
121
|
}
|
|
120
122
|
#admitRaw(ev) {
|
|
123
|
+
const selfId = resolveOnebot11SelfId(ev.self_id);
|
|
124
|
+
if (!this.#stopped && selfId && selfId !== this.selfUserId)
|
|
125
|
+
this.reportSelfUserId(selfId);
|
|
121
126
|
if (!isMessageEvent(ev)) {
|
|
122
127
|
receiveOneBot11SideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, { callApi: (action, params) => callOnebot11Client(this.client, action, params) }, ev, this.#logger);
|
|
123
128
|
return;
|
|
@@ -145,6 +150,19 @@ export class OneBot11WssEndpoint extends ClientEndpoint {
|
|
|
145
150
|
}));
|
|
146
151
|
});
|
|
147
152
|
}
|
|
153
|
+
/** Best-effort 登录账号探测;失败仅 debug,不影响连接。 */
|
|
154
|
+
async #probeSelfUserId() {
|
|
155
|
+
const selfId = await probeOnebot11SelfId(this.client, (error) => {
|
|
156
|
+
this.#logger.debug(formatCompact({
|
|
157
|
+
op: 'onebot11_get_login_info_failed',
|
|
158
|
+
error: error instanceof Error ? error.message : String(error),
|
|
159
|
+
}));
|
|
160
|
+
});
|
|
161
|
+
if (this.#stopped || this.transportState !== 'open')
|
|
162
|
+
return;
|
|
163
|
+
if (selfId && selfId !== this.selfUserId)
|
|
164
|
+
this.reportSelfUserId(selfId);
|
|
165
|
+
}
|
|
148
166
|
#warnPlatformEvent(error) {
|
|
149
167
|
this.#logger.warn(formatCompact({
|
|
150
168
|
op: 'onebot11_platform_event_failed',
|
|
@@ -215,6 +233,8 @@ export class OneBot11WssEndpoint extends ClientEndpoint {
|
|
|
215
233
|
lifecycleHandle.notifyClosed(new Error('OneBot11 reverse WebSocket closed'));
|
|
216
234
|
});
|
|
217
235
|
});
|
|
236
|
+
if (this.#options.probeLoginInfo)
|
|
237
|
+
void this.#probeSelfUserId();
|
|
218
238
|
this.#logger.debug(formatCompact({
|
|
219
239
|
endpoint: this.#options.config.id,
|
|
220
240
|
mode: 'wss',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-onebot11",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "Zhin.js OneBot 11 adapter for Plugin Runtime (WebSocket client)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -45,16 +45,16 @@
|
|
|
45
45
|
"@imhelper/onebot-v11": "1.0.7",
|
|
46
46
|
"imhelper": "1.0.7",
|
|
47
47
|
"ws": "^8.21.1",
|
|
48
|
-
"@zhin.js/adapter": "1.1.
|
|
49
|
-
"@zhin.js/agent-feature": "1.1.
|
|
50
|
-
"@zhin.js/core": "1.1.
|
|
51
|
-
"@zhin.js/feature-kit": "1.1.
|
|
52
|
-
"@zhin.js/host-http": "1.1.
|
|
48
|
+
"@zhin.js/adapter": "1.1.18",
|
|
49
|
+
"@zhin.js/agent-feature": "1.1.5",
|
|
50
|
+
"@zhin.js/core": "1.1.43",
|
|
51
|
+
"@zhin.js/feature-kit": "1.1.4",
|
|
52
|
+
"@zhin.js/host-http": "1.1.5",
|
|
53
53
|
"@zhin.js/im-contract": "1.1.3",
|
|
54
54
|
"@zhin.js/logger": "1.1.1",
|
|
55
|
-
"@zhin.js/permission": "1.1.
|
|
56
|
-
"@zhin.js/skill": "1.1.
|
|
57
|
-
"@zhin.js/tool": "1.1.
|
|
55
|
+
"@zhin.js/permission": "1.1.5",
|
|
56
|
+
"@zhin.js/skill": "1.1.5",
|
|
57
|
+
"@zhin.js/tool": "1.1.5"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/node": "^26.1.2",
|
|
@@ -62,15 +62,15 @@
|
|
|
62
62
|
"typescript": "^6.0.3",
|
|
63
63
|
"vitest": "^4.1.10",
|
|
64
64
|
"zod": "^4.4.3",
|
|
65
|
-
"@zhin.js/host-http": "1.1.
|
|
66
|
-
"zhin.js": "1.1.
|
|
65
|
+
"@zhin.js/host-http": "1.1.5",
|
|
66
|
+
"zhin.js": "1.1.8"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
69
|
"zod": "^4.0.0",
|
|
70
|
-
"@zhin.js/adapter": "^1.1.
|
|
71
|
-
"@zhin.js/command": "^1.1.
|
|
72
|
-
"@zhin.js/core": "^1.1.
|
|
73
|
-
"zhin.js": "^1.1.
|
|
70
|
+
"@zhin.js/adapter": "^1.1.18",
|
|
71
|
+
"@zhin.js/command": "^1.1.6",
|
|
72
|
+
"@zhin.js/core": "^1.1.43",
|
|
73
|
+
"zhin.js": "^1.1.8"
|
|
74
74
|
},
|
|
75
75
|
"peerDependenciesMeta": {
|
|
76
76
|
"@zhin.js/command": {
|
package/src/self-id.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { callOnebot11Client, type Onebot11Client } from './client.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 规范化 OneBot11 平台账号 id(`self_id` / `get_login_info.user_id`)。
|
|
5
|
+
* 非法值、空串、0 均视为未知;绝不使用 `config.id`(那是 Endpoint 名,不是平台账号)。
|
|
6
|
+
*/
|
|
7
|
+
export function resolveOnebot11SelfId(value: unknown): string | undefined {
|
|
8
|
+
if (typeof value === 'number') {
|
|
9
|
+
return Number.isSafeInteger(value) && value > 0 ? String(value) : undefined;
|
|
10
|
+
}
|
|
11
|
+
if (typeof value !== 'string') return undefined;
|
|
12
|
+
const trimmed = value.trim();
|
|
13
|
+
return trimmed === '' || trimmed === '0' ? undefined : trimmed;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Best-effort `get_login_info`;失败返回 undefined 并交给调用方 debug,不抛错。 */
|
|
17
|
+
export async function probeOnebot11SelfId(
|
|
18
|
+
client: Onebot11Client,
|
|
19
|
+
onError: (error: unknown) => void,
|
|
20
|
+
): Promise<string | undefined> {
|
|
21
|
+
try {
|
|
22
|
+
const data = await callOnebot11Client<{ user_id?: number | string }>(client, 'get_login_info');
|
|
23
|
+
return resolveOnebot11SelfId(data?.user_id);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
onError(error);
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/ws-endpoint.ts
CHANGED
|
@@ -42,10 +42,13 @@ import {
|
|
|
42
42
|
type OneBot11WsCreateOptions,
|
|
43
43
|
type OneBot11WsSocket,
|
|
44
44
|
} from './ws-types.js';
|
|
45
|
+
import { probeOnebot11SelfId, resolveOnebot11SelfId } from './self-id.js';
|
|
45
46
|
import { callOnebot11Client, createOnebot11EndpointClient, forwardOnebot11ClientEvents, type Onebot11Client } from './client.js';
|
|
46
47
|
|
|
47
48
|
export interface OneBot11WsEndpointOptions {
|
|
48
49
|
readonly id: CapabilityId;
|
|
50
|
+
/** 连接后 best-effort 调用 get_login_info 上报账号(Adapter 工厂开启;默认关闭以免占用首个 echo)。 */
|
|
51
|
+
readonly probeLoginInfo?: boolean;
|
|
49
52
|
readonly config: OneBot11WsConfig;
|
|
50
53
|
readonly createWebSocket?: (
|
|
51
54
|
url: string,
|
|
@@ -63,6 +66,7 @@ export class OneBot11WsEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
63
66
|
readonly content;
|
|
64
67
|
readonly #lifecycle: EndpointLifecycle;
|
|
65
68
|
#ws?: OneBot11WsSocket;
|
|
69
|
+
#stopped = false;
|
|
66
70
|
#requestId = { value: 0 };
|
|
67
71
|
#pending = new Map<string, OneBot11PendingAction>();
|
|
68
72
|
|
|
@@ -101,8 +105,10 @@ export class OneBot11WsEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
101
105
|
|
|
102
106
|
async start(): Promise<void> {
|
|
103
107
|
if (this.#lifecycle.started) return;
|
|
108
|
+
this.#stopped = false;
|
|
104
109
|
try {
|
|
105
110
|
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
111
|
+
if (this.#options.probeLoginInfo) void this.#probeSelfUserId();
|
|
106
112
|
} catch (err) {
|
|
107
113
|
// start 失败必须清理现场(状态复位由基座保证)
|
|
108
114
|
if (this.#ws) {
|
|
@@ -118,11 +124,13 @@ export class OneBot11WsEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
async stop(): Promise<void> {
|
|
127
|
+
this.#stopped = true;
|
|
121
128
|
this.close();
|
|
122
129
|
// 基座负责:清重连/心跳定时器、强关 ws、唤醒 stop-during-connect 竞态
|
|
123
130
|
await this.#lifecycle.stop();
|
|
124
131
|
rejectAllPending(this.#pending);
|
|
125
132
|
this.#ws = undefined;
|
|
133
|
+
this.reportSelfUserId(undefined);
|
|
126
134
|
}
|
|
127
135
|
|
|
128
136
|
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
@@ -156,6 +164,8 @@ export class OneBot11WsEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
#admitRaw(ev: OneBot11Event): void {
|
|
167
|
+
const selfId = resolveOnebot11SelfId(ev.self_id);
|
|
168
|
+
if (!this.#stopped && selfId && selfId !== this.selfUserId) this.reportSelfUserId(selfId);
|
|
159
169
|
if (!isMessageEvent(ev)) {
|
|
160
170
|
receiveOneBot11SideEvent(
|
|
161
171
|
(name, payload) => this.emit(name, payload),
|
|
@@ -191,6 +201,18 @@ export class OneBot11WsEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
191
201
|
});
|
|
192
202
|
}
|
|
193
203
|
|
|
204
|
+
/** Best-effort 登录账号探测;失败仅 debug,不影响连接。 */
|
|
205
|
+
async #probeSelfUserId(): Promise<void> {
|
|
206
|
+
const selfId = await probeOnebot11SelfId(this.client, (error) => {
|
|
207
|
+
this.#logger.debug(formatCompact({
|
|
208
|
+
op: 'onebot11_get_login_info_failed',
|
|
209
|
+
error: error instanceof Error ? error.message : String(error),
|
|
210
|
+
}));
|
|
211
|
+
});
|
|
212
|
+
if (this.#stopped || this.transportState !== 'open') return;
|
|
213
|
+
if (selfId && selfId !== this.selfUserId) this.reportSelfUserId(selfId);
|
|
214
|
+
}
|
|
215
|
+
|
|
194
216
|
#warnPlatformEvent(error: unknown): void {
|
|
195
217
|
this.#logger.warn(formatCompact({
|
|
196
218
|
op: 'onebot11_platform_event_failed',
|
package/src/wss-endpoint.ts
CHANGED
|
@@ -41,10 +41,13 @@ import {
|
|
|
41
41
|
type OneBot11PendingAction,
|
|
42
42
|
type OneBot11WsSocket,
|
|
43
43
|
} from './ws-types.js';
|
|
44
|
+
import { probeOnebot11SelfId, resolveOnebot11SelfId } from './self-id.js';
|
|
44
45
|
import { callOnebot11Client, createOnebot11EndpointClient, forwardOnebot11ClientEvents, type Onebot11Client } from './client.js';
|
|
45
46
|
|
|
46
47
|
export interface OneBot11WssEndpointOptions {
|
|
47
48
|
readonly id: CapabilityId;
|
|
49
|
+
/** 连接后 best-effort 调用 get_login_info 上报账号(Adapter 工厂开启)。 */
|
|
50
|
+
readonly probeLoginInfo?: boolean;
|
|
48
51
|
readonly http: HttpHost;
|
|
49
52
|
readonly config: OneBot11WssConfig;
|
|
50
53
|
}
|
|
@@ -139,6 +142,7 @@ export class OneBot11WssEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
139
142
|
rejectAllPending(this.#pending);
|
|
140
143
|
this.#ws = undefined;
|
|
141
144
|
this.#started = false;
|
|
145
|
+
this.reportSelfUserId(undefined);
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
@@ -165,6 +169,8 @@ export class OneBot11WssEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
165
169
|
}
|
|
166
170
|
|
|
167
171
|
#admitRaw(ev: OneBot11Event): void {
|
|
172
|
+
const selfId = resolveOnebot11SelfId(ev.self_id);
|
|
173
|
+
if (!this.#stopped && selfId && selfId !== this.selfUserId) this.reportSelfUserId(selfId);
|
|
168
174
|
if (!isMessageEvent(ev)) {
|
|
169
175
|
receiveOneBot11SideEvent(
|
|
170
176
|
(name, payload) => this.emit(name, payload),
|
|
@@ -199,6 +205,18 @@ export class OneBot11WssEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
199
205
|
});
|
|
200
206
|
}
|
|
201
207
|
|
|
208
|
+
/** Best-effort 登录账号探测;失败仅 debug,不影响连接。 */
|
|
209
|
+
async #probeSelfUserId(): Promise<void> {
|
|
210
|
+
const selfId = await probeOnebot11SelfId(this.client, (error) => {
|
|
211
|
+
this.#logger.debug(formatCompact({
|
|
212
|
+
op: 'onebot11_get_login_info_failed',
|
|
213
|
+
error: error instanceof Error ? error.message : String(error),
|
|
214
|
+
}));
|
|
215
|
+
});
|
|
216
|
+
if (this.#stopped || this.transportState !== 'open') return;
|
|
217
|
+
if (selfId && selfId !== this.selfUserId) this.reportSelfUserId(selfId);
|
|
218
|
+
}
|
|
219
|
+
|
|
202
220
|
#warnPlatformEvent(error: unknown): void {
|
|
203
221
|
this.#logger.warn(formatCompact({
|
|
204
222
|
op: 'onebot11_platform_event_failed',
|
|
@@ -263,6 +281,7 @@ export class OneBot11WssEndpoint extends ClientEndpoint<Onebot11Client> {
|
|
|
263
281
|
lifecycleHandle.notifyClosed(new Error('OneBot11 reverse WebSocket closed'));
|
|
264
282
|
});
|
|
265
283
|
});
|
|
284
|
+
if (this.#options.probeLoginInfo) void this.#probeSelfUserId();
|
|
266
285
|
this.#logger.debug(formatCompact({
|
|
267
286
|
endpoint: this.#options.config.id,
|
|
268
287
|
mode: 'wss',
|