@zhin.js/adapter-onebot12 6.0.0 → 6.0.1
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 +20 -0
- package/README.md +21 -2
- package/adapters/onebot12.js +0 -9
- package/adapters/onebot12.ts +0 -9
- package/lib/client.d.ts +20 -0
- package/lib/client.js +33 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +2 -0
- package/lib/onebot12-endpoint-commands.d.ts +1 -1
- package/lib/protocol.d.ts +2 -2
- package/lib/protocol.js +1 -1
- package/lib/side-event-dispatch.d.ts +2 -2
- package/lib/side-event-dispatch.js +3 -3
- package/lib/webhook.d.ts +5 -11
- package/lib/webhook.js +34 -50
- package/lib/ws-endpoint.d.ts +5 -12
- package/lib/ws-endpoint.js +30 -30
- package/lib/wss-endpoint.d.ts +8 -11
- package/lib/wss-endpoint.js +58 -66
- package/package.json +14 -11
- package/src/client.ts +81 -0
- package/src/index.ts +16 -0
- package/src/protocol.ts +2 -2
- package/src/side-event-dispatch.ts +4 -4
- package/src/webhook.ts +42 -54
- package/src/ws-endpoint.ts +37 -36
- package/src/wss-endpoint.ts +66 -69
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @zhin.js/adapter-onebot12
|
|
2
2
|
|
|
3
|
+
## 6.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4e8117c: Expose the published imhelper protocol Clients from every Endpoint, preserve native action responses, and route host-owned HTTP, WebSocket, and raw ingress through the Client APIs. Add the shared `ClientEndpoint` deep base so concrete transports inherit one open-gated Client event bridge, and move reverse WebSocket lifecycle and heartbeat cleanup onto the common lifecycle state machine.
|
|
8
|
+
- 1fc78bc: Unify native platform Client access behind the literal `adapter` discriminant. Handlers infer both native events and Clients, while command, inbound/outbound middleware, and both Agent tool authoring surfaces expose the exact operation-scoped Client through a lazy `$client` getter. Definitions without `adapter` keep `$client` typed as `unknown`, and runtime dispatch rejects adapter mismatches before resolving the Client. Bundled platform tools now use this single path instead of model-provided endpoint ids and adapter-specific dependency wrappers. Every adapter registers one Client/EventMap contract, and protocol adapters including NapCat, Milky, OneBot and Satori now produce transport-independent Client objects rather than letting Endpoint instances impersonate Clients.
|
|
9
|
+
- 2ca9a52: Upgrade the protocol Clients to imhelper 1.0.7, keep receiver ownership exclusively in Endpoint through manual mode, expose structured protocol errors, and support canonical non-message Client events.
|
|
10
|
+
- Updated dependencies [4e8117c]
|
|
11
|
+
- Updated dependencies [54bfd6b]
|
|
12
|
+
- Updated dependencies [12025ee]
|
|
13
|
+
- Updated dependencies [09b14d6]
|
|
14
|
+
- Updated dependencies [1fc78bc]
|
|
15
|
+
- @zhin.js/adapter@1.2.1
|
|
16
|
+
- @zhin.js/core@1.5.14
|
|
17
|
+
- @zhin.js/host-http@1.0.13
|
|
18
|
+
- @zhin.js/command@1.0.16
|
|
19
|
+
- @zhin.js/logger@1.0.77
|
|
20
|
+
- zhin.js@6.0.14
|
|
21
|
+
- @zhin.js/feature-kit@1.0.13
|
|
22
|
+
|
|
3
23
|
## 6.0.0
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Zhin.js [OneBot 12](https://12.onebot.dev/) 适配器(Plugin Runtime)。默
|
|
|
8
8
|
- 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
|
|
9
9
|
- **正向 WebSocket**(`connection: ws`):应用连 OneBot 实现的 WS 服务器
|
|
10
10
|
- `access_token` 鉴权(Bearer + query)
|
|
11
|
-
- 入站经 `
|
|
11
|
+
- 入站经 `Endpoint.emit(...)`;出站 `send({ conversation, payload })`
|
|
12
12
|
|
|
13
13
|
## 安装
|
|
14
14
|
|
|
@@ -19,13 +19,23 @@ pnpm add @zhin.js/adapter-onebot12
|
|
|
19
19
|
## Plugin Runtime
|
|
20
20
|
|
|
21
21
|
- `@zhin.js/adapter` — 约定式 `adapters/onebot12.ts`(`defineAdapter`)
|
|
22
|
-
- `@zhin.js/core` — `
|
|
22
|
+
- `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
|
|
23
23
|
- `zhin.js` — `plugin.ts`(`definePlugin`)
|
|
24
24
|
- 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
|
|
25
25
|
|
|
26
26
|
入站:`gateway.receive({ conversation: ConversationRef, message: { conversation, id }, content, sender, metadata })`
|
|
27
27
|
出站:`send({ conversation, payload })` → WS `send_message`(payload 已由 gateway/core 渲染;无 segment-mapper)
|
|
28
28
|
|
|
29
|
+
每个 Endpoint 的 `$client` 是 `@imhelper/onebot-v12` 的 `OneBotV12Client`。业务代码直接调用
|
|
30
|
+
`$client.call(action, params)` 和 Client 的公开平台能力;Webhook 使用 Client 的
|
|
31
|
+
`acceptHttp()`,双工 WS 则由 Endpoint 分离 `echo` 响应后把事件交给 `ingest()`。
|
|
32
|
+
|
|
33
|
+
## 前置条件
|
|
34
|
+
|
|
35
|
+
1. 启动兼容 OneBot 12 的实现,并确认其支持所选 WS 或 Webhook 模式。
|
|
36
|
+
2. Webhook 出站还需要可用的 `api_url`;反向连接需要实现端可达 Zhin HTTP Host。
|
|
37
|
+
3. 两端配置相同的 `access_token`,生产环境必须启用鉴权。
|
|
38
|
+
|
|
29
39
|
## 最小配置
|
|
30
40
|
|
|
31
41
|
```yaml
|
|
@@ -71,6 +81,15 @@ plugins:
|
|
|
71
81
|
- [OneBot Connect WebSocket](https://12.onebot.dev/connect/communication/websocket/)
|
|
72
82
|
- [适配器概览](https://zhin.js.org/essentials/adapters)
|
|
73
83
|
|
|
84
|
+
## 故障排查
|
|
85
|
+
|
|
86
|
+
| 现象 | 排查 |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| WS 连接失败 | 核对 OneBot 版本、连接方向、URL 与端口 |
|
|
89
|
+
| Webhook 能收不能发 | 检查 `api_url` 可达性与 `send_message` 支持 |
|
|
90
|
+
| 401 或握手失败 | 确认 Header/query token 与实现端一致 |
|
|
91
|
+
| 事件字段无法识别 | 确认实现端发送的是 OneBot 12 而非 v11 结构 |
|
|
92
|
+
|
|
74
93
|
## 许可证
|
|
75
94
|
|
|
76
95
|
MIT License
|
package/adapters/onebot12.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Convention entry: discover `adapters/onebot12.ts` → defineAdapter.
|
|
4
4
|
*/
|
|
5
5
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
6
|
-
import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
|
|
7
6
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
8
7
|
import { OneBot12WebhookEndpoint } from "../lib/webhook.js";
|
|
9
8
|
import { OneBot12WsEndpoint } from "../lib/ws-endpoint.js";
|
|
@@ -24,8 +23,6 @@ export default defineAdapter({
|
|
|
24
23
|
},
|
|
25
24
|
create(context) {
|
|
26
25
|
const config = resolveOneBot12Config(context.config);
|
|
27
|
-
const gateway = context.use(messageGatewayToken);
|
|
28
|
-
const sideEvents = context.use(sideEventGatewayToken);
|
|
29
26
|
// 注册到插件运行时状态(onebot12.endpoint list 的"运行中"数据源)
|
|
30
27
|
context.use(onebot12RuntimeStateToken).endpoints.set(config.id, {
|
|
31
28
|
id: config.id,
|
|
@@ -34,8 +31,6 @@ export default defineAdapter({
|
|
|
34
31
|
if (config.connection === 'webhook') {
|
|
35
32
|
return new OneBot12WebhookEndpoint({
|
|
36
33
|
id: context.id,
|
|
37
|
-
gateway,
|
|
38
|
-
sideEvents,
|
|
39
34
|
http: context.use(httpHostToken),
|
|
40
35
|
config,
|
|
41
36
|
});
|
|
@@ -43,16 +38,12 @@ export default defineAdapter({
|
|
|
43
38
|
if (config.connection === 'wss') {
|
|
44
39
|
return new OneBot12WssEndpoint({
|
|
45
40
|
id: context.id,
|
|
46
|
-
gateway,
|
|
47
|
-
sideEvents,
|
|
48
41
|
http: context.use(httpHostToken),
|
|
49
42
|
config,
|
|
50
43
|
});
|
|
51
44
|
}
|
|
52
45
|
return new OneBot12WsEndpoint({
|
|
53
46
|
id: context.id,
|
|
54
|
-
gateway,
|
|
55
|
-
sideEvents,
|
|
56
47
|
config,
|
|
57
48
|
});
|
|
58
49
|
},
|
package/adapters/onebot12.ts
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Convention entry: discover `adapters/onebot12.ts` → defineAdapter.
|
|
3
3
|
*/
|
|
4
4
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
5
|
-
import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
|
|
6
5
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
7
6
|
import { OneBot12WebhookEndpoint } from '../src/webhook.js';
|
|
8
7
|
import { OneBot12WsEndpoint } from '../src/ws-endpoint.js';
|
|
@@ -38,8 +37,6 @@ export default defineAdapter<OneBot12AdapterConfig>({
|
|
|
38
37
|
},
|
|
39
38
|
create(context) {
|
|
40
39
|
const config = resolveOneBot12Config(context.config);
|
|
41
|
-
const gateway = context.use(messageGatewayToken);
|
|
42
|
-
const sideEvents = context.use(sideEventGatewayToken);
|
|
43
40
|
// 注册到插件运行时状态(onebot12.endpoint list 的"运行中"数据源)
|
|
44
41
|
context.use(onebot12RuntimeStateToken).endpoints.set(config.id, {
|
|
45
42
|
id: config.id,
|
|
@@ -48,8 +45,6 @@ export default defineAdapter<OneBot12AdapterConfig>({
|
|
|
48
45
|
if (config.connection === 'webhook') {
|
|
49
46
|
return new OneBot12WebhookEndpoint({
|
|
50
47
|
id: context.id,
|
|
51
|
-
gateway,
|
|
52
|
-
sideEvents,
|
|
53
48
|
http: context.use(httpHostToken),
|
|
54
49
|
config,
|
|
55
50
|
});
|
|
@@ -57,16 +52,12 @@ export default defineAdapter<OneBot12AdapterConfig>({
|
|
|
57
52
|
if (config.connection === 'wss') {
|
|
58
53
|
return new OneBot12WssEndpoint({
|
|
59
54
|
id: context.id,
|
|
60
|
-
gateway,
|
|
61
|
-
sideEvents,
|
|
62
55
|
http: context.use(httpHostToken),
|
|
63
56
|
config,
|
|
64
57
|
});
|
|
65
58
|
}
|
|
66
59
|
return new OneBot12WsEndpoint({
|
|
67
60
|
id: context.id,
|
|
68
|
-
gateway,
|
|
69
|
-
sideEvents,
|
|
70
61
|
config,
|
|
71
62
|
});
|
|
72
63
|
},
|
package/lib/client.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OneBotV12Client, type OneBotV12Event as ImHelperOneBot12Event, type OneBotV12Response } from '@imhelper/onebot-v12';
|
|
2
|
+
import { type EventMap, type ImHelperEventMap } from 'imhelper';
|
|
3
|
+
import { type ClientEventPayloads } from 'zhin.js/adapter';
|
|
4
|
+
import type { ResolvedOneBot12Config } from './protocol.js';
|
|
5
|
+
export { OneBotV12Client as Onebot12Client } from '@imhelper/onebot-v12';
|
|
6
|
+
export type Onebot12ApiCall = (action: string, params?: Record<string, unknown>) => Promise<OneBotV12Response>;
|
|
7
|
+
type Onebot12ClientEvents = ImHelperEventMap<string, ImHelperOneBot12Event, EventMap<string>>;
|
|
8
|
+
export type Onebot12ClientEventMap = ClientEventPayloads<Onebot12ClientEvents>;
|
|
9
|
+
export declare function createOnebot12EndpointClient(config: ResolvedOneBot12Config, request: Onebot12ApiCall): OneBotV12Client;
|
|
10
|
+
export declare function callOnebot12Client<T = unknown>(client: OneBotV12Client, action: string, params?: Record<string, unknown>): Promise<T | undefined>;
|
|
11
|
+
export declare function forwardOnebot12ClientEvents(client: OneBotV12Client, receive: (name: string, payload: unknown) => void): () => void;
|
|
12
|
+
declare module '@zhin.js/feature-kit' {
|
|
13
|
+
interface AdapterClientRegistry {
|
|
14
|
+
readonly onebot12: {
|
|
15
|
+
readonly client: OneBotV12Client;
|
|
16
|
+
readonly events: Onebot12ClientEventMap;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export declare const onebot12Client: import("@zhin.js/adapter").EndpointClientToken<OneBotV12Client, ClientEventPayloads<Onebot12ClientEvents>>;
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { OneBotV12Client, } from '@imhelper/onebot-v12';
|
|
2
|
+
import { EventFactory } from 'imhelper';
|
|
3
|
+
import { defineEndpointClient, forwardEndpointClientEvents, } from 'zhin.js/adapter';
|
|
4
|
+
export { OneBotV12Client as Onebot12Client } from '@imhelper/onebot-v12';
|
|
5
|
+
export function createOnebot12EndpointClient(config, request) {
|
|
6
|
+
const baseUrl = config.connection === 'ws'
|
|
7
|
+
? config.url.replace(/^ws(s?):/, 'http$1:')
|
|
8
|
+
: config.connection === 'webhook' && config.api_url
|
|
9
|
+
? config.api_url
|
|
10
|
+
: 'http://localhost';
|
|
11
|
+
return new OneBotV12Client({
|
|
12
|
+
baseUrl,
|
|
13
|
+
selfId: config.id,
|
|
14
|
+
accessToken: config.access_token,
|
|
15
|
+
receiveMode: 'manual',
|
|
16
|
+
call: request,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export async function callOnebot12Client(client, action, params) {
|
|
20
|
+
const response = await client.call(action, params);
|
|
21
|
+
if (response.status !== 'ok') {
|
|
22
|
+
throw new Error(`OneBot 12 API ${action}: retcode=${response.retcode}${response.message ? ` ${response.message}` : ''}`);
|
|
23
|
+
}
|
|
24
|
+
return response.data;
|
|
25
|
+
}
|
|
26
|
+
const onebot12ClientEventNames = Object.freeze([
|
|
27
|
+
...EventFactory.getSupportedEventTypes(),
|
|
28
|
+
'event',
|
|
29
|
+
]);
|
|
30
|
+
export function forwardOnebot12ClientEvents(client, receive) {
|
|
31
|
+
return forwardEndpointClientEvents(client, onebot12ClientEventNames, receive);
|
|
32
|
+
}
|
|
33
|
+
export const onebot12Client = defineEndpointClient('onebot12');
|
package/lib/index.d.ts
CHANGED
|
@@ -4,3 +4,7 @@ export { OneBot12WsEndpoint, type OneBot12WsEndpointOptions, } from './ws-endpoi
|
|
|
4
4
|
export { OneBot12WssEndpoint, type OneBot12WssEndpointOptions, } from './wss-endpoint.js';
|
|
5
5
|
export type { OneBot12WsSocket, OneBot12WsCreateOptions } from './ws-types.js';
|
|
6
6
|
export { verifyOneBotAccessToken } from './wss-auth.js';
|
|
7
|
+
export { Onebot12Client, onebot12Client, type Onebot12ClientEventMap, } from './client.js';
|
|
8
|
+
export type { OneBotV12ActionUrlResolver, OneBotV12AdapterConfig as ImHelperOneBotV12AdapterConfig, OneBotV12Call, OneBotV12ClientConfig, OneBotV12Event as ImHelperOneBotV12Event, OneBotV12Response, } from '@imhelper/onebot-v12';
|
|
9
|
+
export { ProtocolError } from '@imhelper/onebot-v12';
|
|
10
|
+
export type { ProtocolErrorKind, ProtocolErrorOptions } from 'imhelper';
|
package/lib/index.js
CHANGED
|
@@ -3,3 +3,5 @@ export { OneBot12WebhookEndpoint, } from './webhook.js';
|
|
|
3
3
|
export { OneBot12WsEndpoint, } from './ws-endpoint.js';
|
|
4
4
|
export { OneBot12WssEndpoint, } from './wss-endpoint.js';
|
|
5
5
|
export { verifyOneBotAccessToken } from './wss-auth.js';
|
|
6
|
+
export { Onebot12Client, onebot12Client, } from './client.js';
|
|
7
|
+
export { ProtocolError } from '@imhelper/onebot-v12';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const onebot12EndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage>>>;
|
|
1
|
+
export declare const onebot12EndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
|
package/lib/protocol.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export interface OneBot12Event {
|
|
|
66
66
|
type: 'meta' | 'message' | 'notice' | 'request';
|
|
67
67
|
detail_type: string;
|
|
68
68
|
sub_type: string;
|
|
69
|
-
self
|
|
69
|
+
self: OneBot12Self;
|
|
70
70
|
message_id?: string;
|
|
71
71
|
message?: OneBot12Segment[];
|
|
72
72
|
alt_message?: string;
|
|
@@ -115,7 +115,7 @@ export declare function getChannelId(ev: OneBot12Event): string;
|
|
|
115
115
|
* group 容器内的 private 会话。
|
|
116
116
|
*/
|
|
117
117
|
export declare function onebot12InboundConversation(endpointKey: string, ev: OneBot12Event): ConversationRef;
|
|
118
|
-
/** Build inbound text for
|
|
118
|
+
/** Build inbound text for OutboundMessageService.receive */
|
|
119
119
|
export declare function formatInboundContent(ev: OneBot12Event): string;
|
|
120
120
|
/**
|
|
121
121
|
* Runtime Message sender 必须是用户 ID(agent bridge 以 sender 与 endpointMaster 比对)。
|
package/lib/protocol.js
CHANGED
|
@@ -103,7 +103,7 @@ export function onebot12InboundConversation(endpointKey, ev) {
|
|
|
103
103
|
: {}),
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
|
-
/** Build inbound text for
|
|
106
|
+
/** Build inbound text for OutboundMessageService.receive */
|
|
107
107
|
export function formatInboundContent(ev) {
|
|
108
108
|
if (Array.isArray(ev.message)) {
|
|
109
109
|
return ev.message
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EndpointEventEmitter } from 'zhin.js/adapter';
|
|
2
2
|
import { type getAdapterLogger } from '@zhin.js/logger';
|
|
3
3
|
import type { OneBot12Event } from './protocol.js';
|
|
4
4
|
export interface OneBot12SideEventCaller {
|
|
5
5
|
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
6
6
|
}
|
|
7
|
-
export declare function receiveOneBot12SideEvent(
|
|
7
|
+
export declare function receiveOneBot12SideEvent(emit: EndpointEventEmitter, endpointKey: string, caller: OneBot12SideEventCaller, raw: OneBot12Event, logger: ReturnType<typeof getAdapterLogger>): void;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { receiveOneBotLikeSideEvent } from '@zhin.js/core';
|
|
2
2
|
import { formatCompact } from '@zhin.js/logger';
|
|
3
|
-
export function receiveOneBot12SideEvent(
|
|
4
|
-
if (!
|
|
3
|
+
export function receiveOneBot12SideEvent(emit, endpointKey, caller, raw, logger) {
|
|
4
|
+
if (!emit)
|
|
5
5
|
return;
|
|
6
6
|
const record = raw;
|
|
7
7
|
const eventType = String(record.type ?? record.post_type ?? '');
|
|
8
8
|
const detailType = String(record.detail_type ?? '');
|
|
9
9
|
const isRequest = eventType === 'request' || eventType.startsWith('request.');
|
|
10
10
|
const isFriend = detailType.includes('friend') || String(record.request_type ?? '') === 'friend';
|
|
11
|
-
void receiveOneBotLikeSideEvent(
|
|
11
|
+
void receiveOneBotLikeSideEvent(emit, {
|
|
12
12
|
adapter: 'onebot12',
|
|
13
13
|
endpointKey,
|
|
14
14
|
platform: 'onebot',
|
package/lib/webhook.d.ts
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
|
|
1
|
+
import { ClientEndpoint, type EndpointControl, type EndpointManagement, type EndpointSendRequest } from 'zhin.js/adapter';
|
|
3
2
|
import type { HttpHost } from '@zhin.js/host-http';
|
|
4
3
|
import type { CapabilityId } from 'zhin.js';
|
|
5
|
-
import { callOneBot12Action, type
|
|
4
|
+
import { callOneBot12Action, type OneBot12WebhookConfig } from './protocol.js';
|
|
5
|
+
import { type Onebot12Client } from './client.js';
|
|
6
6
|
export interface OneBot12WebhookEndpointOptions {
|
|
7
7
|
readonly id: CapabilityId;
|
|
8
|
-
readonly gateway: MessageGateway;
|
|
9
|
-
readonly sideEvents?: SideEventGateway;
|
|
10
8
|
readonly http: HttpHost;
|
|
11
9
|
readonly config: OneBot12WebhookConfig;
|
|
12
10
|
readonly callAction?: typeof callOneBot12Action;
|
|
13
11
|
}
|
|
14
|
-
export declare class OneBot12WebhookEndpoint
|
|
12
|
+
export declare class OneBot12WebhookEndpoint extends ClientEndpoint<Onebot12Client> {
|
|
15
13
|
#private;
|
|
14
|
+
readonly client: Onebot12Client;
|
|
16
15
|
readonly management: EndpointManagement;
|
|
17
16
|
readonly control: EndpointControl;
|
|
18
17
|
readonly content: import("@zhin.js/adapter").EndpointContentPort;
|
|
19
18
|
constructor(options: OneBot12WebhookEndpointOptions);
|
|
20
19
|
start(): Promise<void>;
|
|
21
|
-
open(): void;
|
|
22
|
-
close(): void;
|
|
23
20
|
stop(): Promise<void>;
|
|
24
21
|
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
25
22
|
recallMessage(messageId: string): Promise<void>;
|
|
26
|
-
/** Public API for management surface / callers;webhook 模式走 api_url。 */
|
|
27
|
-
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
28
|
-
admit(ev: OneBot12Event): void;
|
|
29
23
|
}
|
package/lib/webhook.js
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
|
-
import { createRecallEndpointControl, } from 'zhin.js/adapter';
|
|
1
|
+
import { ClientEndpoint, createRecallEndpointControl, } from 'zhin.js/adapter';
|
|
2
2
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
3
3
|
import { createOneBot12EndpointManagement } from './endpoint-management.js';
|
|
4
4
|
import { buildSendMessageParams, callOneBot12Action, formatInboundContent, formatOutboundSegments, isBotMentioned, isMessageEvent, onebot12InboundConversation, senderNickname, senderUserId, uploadOneBot12MediaSegments, } from './protocol.js';
|
|
5
5
|
import { receiveOneBot12SideEvent } from './side-event-dispatch.js';
|
|
6
6
|
import { createOneBot12ContentPort } from './content-port.js';
|
|
7
|
+
import { callOnebot12Client, createOnebot12EndpointClient, forwardOnebot12ClientEvents } from './client.js';
|
|
7
8
|
import { verifyOneBotAccessToken } from './wss-auth.js';
|
|
8
9
|
const logger = getLogger('onebot12');
|
|
9
|
-
export class OneBot12WebhookEndpoint {
|
|
10
|
+
export class OneBot12WebhookEndpoint extends ClientEndpoint {
|
|
11
|
+
client;
|
|
10
12
|
#options;
|
|
11
|
-
management
|
|
13
|
+
management;
|
|
12
14
|
control = createRecallEndpointControl((id) => this.recallMessage(id));
|
|
13
|
-
content
|
|
15
|
+
content;
|
|
14
16
|
#callAction;
|
|
15
17
|
#routeReleases = [];
|
|
16
|
-
#open = false;
|
|
17
18
|
#started = false;
|
|
18
19
|
constructor(options) {
|
|
20
|
+
super();
|
|
19
21
|
this.#options = options;
|
|
20
22
|
this.#callAction = options.callAction ?? callOneBot12Action;
|
|
23
|
+
this.client = createOnebot12EndpointClient(options.config, (action, params) => this.#callApi(action, params));
|
|
24
|
+
const callApi = (action, params) => callOnebot12Client(this.client, action, params);
|
|
25
|
+
this.management = createOneBot12EndpointManagement({ callApi });
|
|
26
|
+
this.content = createOneBot12ContentPort(callApi);
|
|
27
|
+
this.bindClientEvents((receive) => forwardOnebot12ClientEvents(this.client, receive), (name, payload) => {
|
|
28
|
+
if (name === 'event')
|
|
29
|
+
this.#admitRaw(payload);
|
|
30
|
+
}, (_name, error) => this.#warnPlatformEvent(error));
|
|
21
31
|
}
|
|
22
32
|
async start() {
|
|
23
33
|
if (this.#started)
|
|
@@ -40,21 +50,15 @@ export class OneBot12WebhookEndpoint {
|
|
|
40
50
|
path: this.#options.config.path,
|
|
41
51
|
}));
|
|
42
52
|
}
|
|
43
|
-
open() {
|
|
44
|
-
this.#open = true;
|
|
45
|
-
}
|
|
46
|
-
close() {
|
|
47
|
-
this.#open = false;
|
|
48
|
-
}
|
|
49
53
|
async stop() {
|
|
50
|
-
this
|
|
54
|
+
this.close();
|
|
51
55
|
for (const release of this.#routeReleases.splice(0))
|
|
52
56
|
release();
|
|
53
57
|
this.#started = false;
|
|
54
58
|
logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.id }));
|
|
55
59
|
}
|
|
56
60
|
async send({ conversation, payload }) {
|
|
57
|
-
const materialized = await uploadOneBot12MediaSegments(payload, (action, params) => this.
|
|
61
|
+
const materialized = await uploadOneBot12MediaSegments(payload, (action, params) => callOnebot12Client(this.client, action, params), (error) => {
|
|
58
62
|
logger.warn(formatCompact({
|
|
59
63
|
op: 'onebot12_upload_failed',
|
|
60
64
|
endpoint: this.#options.config.id,
|
|
@@ -63,7 +67,7 @@ export class OneBot12WebhookEndpoint {
|
|
|
63
67
|
});
|
|
64
68
|
const message = formatOutboundSegments(materialized);
|
|
65
69
|
const params = buildSendMessageParams(conversation, message);
|
|
66
|
-
const data = await this.
|
|
70
|
+
const data = await callOnebot12Client(this.client, 'send_message', params);
|
|
67
71
|
const messageId = data?.message_id ?? '';
|
|
68
72
|
logger.debug(formatCompact({
|
|
69
73
|
op: 'onebot12_send',
|
|
@@ -77,29 +81,25 @@ export class OneBot12WebhookEndpoint {
|
|
|
77
81
|
async recallMessage(messageId) {
|
|
78
82
|
if (!messageId)
|
|
79
83
|
return;
|
|
80
|
-
await this.
|
|
84
|
+
await callOnebot12Client(this.client, 'delete_message', { message_id: messageId });
|
|
81
85
|
}
|
|
82
|
-
|
|
83
|
-
async callApi(action, params = {}) {
|
|
86
|
+
async #callApi(action, params = {}) {
|
|
84
87
|
const apiUrl = this.#options.config.api_url;
|
|
85
88
|
if (!apiUrl) {
|
|
86
89
|
throw new Error('OneBot12 connection:webhook requires api_url for outbound api');
|
|
87
90
|
}
|
|
88
|
-
|
|
89
|
-
return resp.data;
|
|
91
|
+
return this.#callAction({ url: apiUrl, access_token: this.#options.config.access_token }, action, params);
|
|
90
92
|
}
|
|
91
|
-
|
|
92
|
-
if (!this.#open)
|
|
93
|
-
return;
|
|
93
|
+
#admitRaw(ev) {
|
|
94
94
|
if (!isMessageEvent(ev)) {
|
|
95
|
-
receiveOneBot12SideEvent(this
|
|
95
|
+
receiveOneBot12SideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, { callApi: (action, params) => callOnebot12Client(this.client, action, params) }, ev, logger);
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
98
|
const conversation = onebot12InboundConversation(String(this.#options.id), ev);
|
|
99
99
|
const content = formatInboundContent(ev);
|
|
100
100
|
const nickname = senderNickname(ev);
|
|
101
101
|
const mentioned = isBotMentioned(ev);
|
|
102
|
-
void this
|
|
102
|
+
void this.emit('message.receive', {
|
|
103
103
|
conversation,
|
|
104
104
|
message: { conversation, id: ev.message_id },
|
|
105
105
|
content,
|
|
@@ -124,6 +124,12 @@ export class OneBot12WebhookEndpoint {
|
|
|
124
124
|
}));
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
|
+
#warnPlatformEvent(error) {
|
|
128
|
+
logger.warn(formatCompact({
|
|
129
|
+
op: 'onebot12_platform_event_failed',
|
|
130
|
+
error: error instanceof Error ? error.message : String(error),
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
127
133
|
#setupRoutes() {
|
|
128
134
|
const path = this.#options.config.path;
|
|
129
135
|
this.#routeReleases.push(this.#options.http.route('POST', path, async (request, response) => {
|
|
@@ -137,20 +143,12 @@ export class OneBot12WebhookEndpoint {
|
|
|
137
143
|
response.end(JSON.stringify({ message: 'Unauthorized' }));
|
|
138
144
|
return;
|
|
139
145
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
ev = JSON.parse(raw);
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
response.writeHead(400, { 'Content-Type': 'application/json' });
|
|
147
|
-
response.end(JSON.stringify({ message: 'Invalid JSON' }));
|
|
146
|
+
if (!this.clientEventsOpen) {
|
|
147
|
+
response.writeHead(200, { 'Content-Type': 'application/json' });
|
|
148
|
+
response.end(JSON.stringify({ status: 'ok' }));
|
|
148
149
|
return;
|
|
149
150
|
}
|
|
150
|
-
|
|
151
|
-
this.admit(ev);
|
|
152
|
-
response.writeHead(200, { 'Content-Type': 'application/json' });
|
|
153
|
-
response.end(JSON.stringify({ status: 'ok' }));
|
|
151
|
+
await this.client.acceptHttp(request, response);
|
|
154
152
|
}
|
|
155
153
|
catch (error) {
|
|
156
154
|
logger.error('OneBot12 webhook error:', error);
|
|
@@ -161,17 +159,3 @@ export class OneBot12WebhookEndpoint {
|
|
|
161
159
|
}
|
|
162
160
|
}
|
|
163
161
|
}
|
|
164
|
-
async function readRequestBody(request) {
|
|
165
|
-
const chunks = [];
|
|
166
|
-
let size = 0;
|
|
167
|
-
for await (const chunk of request) {
|
|
168
|
-
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
169
|
-
size += buffer.length;
|
|
170
|
-
if (size > 1_048_576) {
|
|
171
|
-
request.destroy();
|
|
172
|
-
throw new Error('Request body exceeds 1MB');
|
|
173
|
-
}
|
|
174
|
-
chunks.push(buffer);
|
|
175
|
-
}
|
|
176
|
-
return Buffer.concat(chunks).toString('utf8');
|
|
177
|
-
}
|
package/lib/ws-endpoint.d.ts
CHANGED
|
@@ -1,29 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
|
|
1
|
+
import { ClientEndpoint, type EndpointControl, type EndpointManagement, type EndpointSendRequest } from 'zhin.js/adapter';
|
|
3
2
|
import type { CapabilityId } from 'zhin.js';
|
|
4
|
-
import { type
|
|
3
|
+
import { type OneBot12WsConfig } from './protocol.js';
|
|
4
|
+
import { type Onebot12Client } from './client.js';
|
|
5
5
|
import { type OneBot12WsCreateOptions, type OneBot12WsSocket } from './ws-types.js';
|
|
6
6
|
export interface OneBot12WsEndpointOptions {
|
|
7
7
|
readonly id: CapabilityId;
|
|
8
|
-
readonly gateway: MessageGateway;
|
|
9
|
-
readonly sideEvents?: SideEventGateway;
|
|
10
8
|
readonly config: OneBot12WsConfig;
|
|
11
9
|
readonly createWebSocket?: (url: string, options: OneBot12WsCreateOptions) => OneBot12WsSocket;
|
|
12
10
|
}
|
|
13
|
-
export declare class OneBot12WsEndpoint
|
|
11
|
+
export declare class OneBot12WsEndpoint extends ClientEndpoint<Onebot12Client> {
|
|
14
12
|
#private;
|
|
13
|
+
readonly client: Onebot12Client;
|
|
15
14
|
readonly management: EndpointManagement;
|
|
16
15
|
readonly control: EndpointControl;
|
|
17
16
|
readonly content: import("@zhin.js/adapter").EndpointContentPort;
|
|
18
17
|
constructor(options: OneBot12WsEndpointOptions);
|
|
19
18
|
start(): Promise<void>;
|
|
20
|
-
open(): void;
|
|
21
|
-
close(): void;
|
|
22
19
|
stop(): Promise<void>;
|
|
23
20
|
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
24
21
|
recallMessage(messageId: string): Promise<void>;
|
|
25
|
-
/** Public API for management surface / callers. */
|
|
26
|
-
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
27
|
-
/** Test / internal: admit a parsed event when the endpoint is open. */
|
|
28
|
-
admit(ev: OneBot12Event): void;
|
|
29
22
|
}
|