@zhin.js/adapter-onebot12 0.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot-wss.d.ts","sourceRoot":"","sources":["../src/bot-wss.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAW,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAiD,MAAM,YAAY,CAAC;AAClH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,qBAAa,iBAAkB,SAAQ,YAAa,YAAW,GAAG,CAAC,iBAAiB,EAAE,aAAa,CAAC;;IAazF,OAAO,EAAE,eAAe;IACxB,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,iBAAiB;IAdnC,UAAU,EAAE,OAAO,CAAS;IAG5B,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,eAAe,CAAmH;IAE1I,IAAI,MAAM,6BAET;gBAGQ,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB;IAKnC,IAAI,GAAG,WAEN;IAED,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,UAAU;IAmBZ,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAwDzB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBlC,cAAc,CAAC,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IA8BnD,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBnD,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGhD"}
package/lib/bot-wss.js ADDED
@@ -0,0 +1,173 @@
1
+ /**
2
+ * OneBot 12 反向 WebSocket Bot:应用开 WS 服务端,OneBot 实现连上来
3
+ */
4
+ import WebSocket from 'ws';
5
+ import { EventEmitter } from 'events';
6
+ import { clearInterval, clearTimeout } from 'node:timers';
7
+ import { Message, segment } from 'zhin.js';
8
+ import { formatOneBot12MessagePayload, isMessageEvent, contentToOb12Segments } from './utils.js';
9
+ export class OneBot12WssServer extends EventEmitter {
10
+ adapter;
11
+ router;
12
+ $config;
13
+ $connected = false;
14
+ #wss;
15
+ #client;
16
+ heartbeatTimer;
17
+ requestId = 0;
18
+ pendingRequests = new Map();
19
+ get logger() {
20
+ return this.adapter.plugin.logger;
21
+ }
22
+ constructor(adapter, router, $config) {
23
+ super();
24
+ this.adapter = adapter;
25
+ this.router = router;
26
+ this.$config = $config;
27
+ }
28
+ get $id() {
29
+ return this.$config.name;
30
+ }
31
+ getClient() {
32
+ return this.#client && this.#client.readyState === WebSocket.OPEN ? this.#client : undefined;
33
+ }
34
+ callAction(action, params) {
35
+ const client = this.getClient();
36
+ if (!client)
37
+ return Promise.reject(new Error('反向 WebSocket 未连接'));
38
+ const echo = `ob12wss_${++this.requestId}`;
39
+ const req = { action, params, echo };
40
+ return new Promise((resolve, reject) => {
41
+ const timeout = setTimeout(() => {
42
+ this.pendingRequests.delete(echo);
43
+ reject(new Error(`OneBot12 动作超时: ${action}`));
44
+ }, 30000);
45
+ this.pendingRequests.set(echo, {
46
+ resolve: (data) => resolve(data),
47
+ reject,
48
+ timeout,
49
+ });
50
+ client.send(JSON.stringify(req));
51
+ });
52
+ }
53
+ async $connect() {
54
+ const path = this.$config.path.startsWith('/') ? this.$config.path : `/${this.$config.path}`;
55
+ this.#wss = this.router.ws(path, {
56
+ verifyClient: (info) => {
57
+ const auth = info.req.headers['authorization'];
58
+ if (this.$config.access_token && auth !== `Bearer ${this.$config.access_token}`) {
59
+ this.logger.error('OneBot12 反向 WS 鉴权失败');
60
+ return false;
61
+ }
62
+ return true;
63
+ },
64
+ });
65
+ this.#wss.on('connection', (ws) => {
66
+ if (this.#client && this.#client.readyState === WebSocket.OPEN) {
67
+ this.#client.close();
68
+ }
69
+ this.#client = ws;
70
+ this.$connected = true;
71
+ this.logger.info(`OneBot12 反向 WS 已连接: ${this.$config.name}`);
72
+ ws.on('message', (data) => {
73
+ try {
74
+ const msg = JSON.parse(data.toString());
75
+ if ('echo' in msg && typeof msg.echo === 'string') {
76
+ const resp = msg;
77
+ const pending = this.pendingRequests.get(resp.echo);
78
+ if (pending) {
79
+ this.pendingRequests.delete(resp.echo);
80
+ clearTimeout(pending.timeout);
81
+ if (resp.status === 'ok')
82
+ pending.resolve(resp.data);
83
+ else
84
+ pending.reject(new Error(`OneBot12 retcode=${resp.retcode}: ${resp.message}`));
85
+ }
86
+ return;
87
+ }
88
+ const ev = msg;
89
+ if (ev.type === 'message' && isMessageEvent(ev)) {
90
+ const message = this.$formatMessage(ev);
91
+ this.adapter.emit('message.receive', message);
92
+ this.logger.debug(`${this.$config.name} recv ${message.$channel.type}(${message.$channel.id}):${segment.raw(message.$content)}`);
93
+ }
94
+ }
95
+ catch (error) {
96
+ this.emit('error', error);
97
+ }
98
+ });
99
+ ws.on('close', () => {
100
+ this.$connected = false;
101
+ this.#client = undefined;
102
+ this.logger.warn('OneBot12 反向 WS 断开');
103
+ });
104
+ ws.on('error', (err) => this.logger.error('OneBot12 反向 WS 错误', err));
105
+ });
106
+ }
107
+ async $disconnect() {
108
+ if (this.heartbeatTimer) {
109
+ clearInterval(this.heartbeatTimer);
110
+ this.heartbeatTimer = undefined;
111
+ }
112
+ for (const [, p] of this.pendingRequests) {
113
+ clearTimeout(p.timeout);
114
+ p.reject(new Error('连接已关闭'));
115
+ }
116
+ this.pendingRequests.clear();
117
+ if (this.#client) {
118
+ this.#client.close();
119
+ this.#client = undefined;
120
+ }
121
+ this.#wss?.close();
122
+ this.#wss = undefined;
123
+ this.$connected = false;
124
+ }
125
+ $formatMessage(ev) {
126
+ if (!isMessageEvent(ev)) {
127
+ return Message.from(ev, {
128
+ $id: '',
129
+ $adapter: 'onebot12',
130
+ $bot: this.$config.name,
131
+ $channel: { id: '', type: 'private' },
132
+ $sender: { id: '', name: '' },
133
+ $content: [],
134
+ $raw: '',
135
+ $timestamp: ev.time ?? 0,
136
+ $recall: async () => { },
137
+ $reply: async () => '',
138
+ });
139
+ }
140
+ const payload = formatOneBot12MessagePayload(ev, this.$config.name, (id) => this.$recallMessage(id), (channel, content, _quote) => this.adapter.sendMessage({
141
+ ...channel,
142
+ context: 'onebot12',
143
+ bot: this.$config.name,
144
+ content: content,
145
+ }));
146
+ return Message.from(ev, payload);
147
+ }
148
+ async $sendMessage(options) {
149
+ const message = contentToOb12Segments(options.content);
150
+ const params = { message };
151
+ if (options.type === 'private') {
152
+ params.detail_type = 'private';
153
+ params.user_id = options.id;
154
+ }
155
+ else if (options.type === 'group') {
156
+ params.detail_type = 'group';
157
+ params.group_id = options.id;
158
+ }
159
+ else {
160
+ const [guildId, channelId] = options.id.includes(':') ? options.id.split(':') : [undefined, options.id];
161
+ params.detail_type = 'channel';
162
+ params.channel_id = channelId ?? options.id;
163
+ if (guildId)
164
+ params.guild_id = guildId;
165
+ }
166
+ const data = await this.callAction('send_message', params);
167
+ return data?.message_id ?? '';
168
+ }
169
+ async $recallMessage(id) {
170
+ await this.callAction('delete_message', { message_id: id });
171
+ }
172
+ }
173
+ //# sourceMappingURL=bot-wss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot-wss.js","sourceRoot":"","sources":["../src/bot-wss.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { OneBot12Adapter } from './adapter.js';
2
+ export * from './types.js';
3
+ export { callOneBot12Action } from './api.js';
4
+ export * from './utils.js';
5
+ export { OneBot12WsClient } from './bot-ws.js';
6
+ export { OneBot12WebhookBot } from './bot-webhook.js';
7
+ export { OneBot12WssServer } from './bot-wss.js';
8
+ export { OneBot12Adapter, type OneBot12Bot } from './adapter.js';
9
+ declare module 'zhin.js' {
10
+ namespace Plugin {
11
+ interface Contexts {
12
+ router: import('@zhin.js/http').Router;
13
+ }
14
+ }
15
+ interface Adapters {
16
+ onebot12: OneBot12Adapter;
17
+ }
18
+ }
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjE,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,MAAM,CAAC;QACf,UAAU,QAAQ;YAChB,MAAM,EAAE,OAAO,eAAe,EAAE,MAAM,CAAC;SACxC;KACF;IACD,UAAU,QAAQ;QAChB,QAAQ,EAAE,eAAe,CAAC;KAC3B;CACF"}
package/lib/index.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * OneBot 12 适配器入口:单一适配器,支持正向 WS / Webhook / 反向 WS
3
+ * 协议文档 https://12.onebot.dev/
4
+ */
5
+ import { usePlugin } from 'zhin.js';
6
+ import { OneBot12Adapter } from './adapter.js';
7
+ export * from './types.js';
8
+ export { callOneBot12Action } from './api.js';
9
+ export * from './utils.js';
10
+ export { OneBot12WsClient } from './bot-ws.js';
11
+ export { OneBot12WebhookBot } from './bot-webhook.js';
12
+ export { OneBot12WssServer } from './bot-wss.js';
13
+ export { OneBot12Adapter } from './adapter.js';
14
+ const { provide } = usePlugin();
15
+ provide({
16
+ name: 'onebot12',
17
+ description: 'OneBot 12 协议适配器(正向 WS / Webhook / 反向 WS)',
18
+ mounted: async (p) => {
19
+ const adapter = new OneBot12Adapter(p);
20
+ await adapter.start();
21
+ return adapter;
22
+ },
23
+ dispose: async (adapter) => {
24
+ await adapter.stop();
25
+ },
26
+ });
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAA6B,MAAM,SAAS,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAoB,MAAM,cAAc,CAAC;AAajE,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;AAChC,OAAO,CAAC;IACN,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,0CAA0C;IACvD,OAAO,EAAE,KAAK,EAAE,CAAS,EAAE,EAAE;QAC3B,MAAM,OAAO,GAAG,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAwB,EAAE,EAAE;QAC1C,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;CACgC,CAAC,CAAC"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,77 @@
1
+ /**
2
+ * OneBot 12 适配器类型(参考 https://12.onebot.dev/ )
3
+ */
4
+ /** 配置公共字段;单一适配器 context 均为 'onebot12',连接方式由 connection 区分 */
5
+ export interface OneBot12ConfigBase {
6
+ context: 'onebot12';
7
+ name: string;
8
+ /** 访问令牌,鉴权用 */
9
+ access_token?: string;
10
+ }
11
+ /** 正向 WebSocket:应用连 OneBot 实现的 WS 服务器 */
12
+ export interface OneBot12WsConfig extends OneBot12ConfigBase {
13
+ connection: 'ws';
14
+ /** OneBot 实现提供的 WebSocket 地址,如 ws://127.0.0.1:6700 */
15
+ url: string;
16
+ reconnect_interval?: number;
17
+ heartbeat_interval?: number;
18
+ }
19
+ /** HTTP Webhook:OneBot 实现 POST 事件到应用提供的 path */
20
+ export interface OneBot12WebhookConfig extends OneBot12ConfigBase {
21
+ connection: 'webhook';
22
+ /** 应用接收事件的 POST 路径 */
23
+ path: string;
24
+ /** 可选:OneBot 实现的 HTTP 端点,用于发消息等动作(实现 POST 事件到我们,我们 POST 动作到该 url) */
25
+ api_url?: string;
26
+ }
27
+ /** 反向 WebSocket:应用开 WS 服务端,OneBot 实现连上来 */
28
+ export interface OneBot12WssConfig extends OneBot12ConfigBase {
29
+ connection: 'wss';
30
+ /** 应用侧 WS 路径 */
31
+ path: string;
32
+ heartbeat_interval?: number;
33
+ }
34
+ export type OneBot12BotConfig = OneBot12WsConfig | OneBot12WebhookConfig | OneBot12WssConfig;
35
+ /** 机器人自身标识(事件与动作中的 self) */
36
+ export interface OneBot12Self {
37
+ platform: string;
38
+ user_id: string;
39
+ }
40
+ /** 事件(实现推送给应用) */
41
+ export interface OneBot12Event {
42
+ id: string;
43
+ time: number;
44
+ type: 'meta' | 'message' | 'notice' | 'request';
45
+ detail_type: string;
46
+ sub_type: string;
47
+ self?: OneBot12Self;
48
+ message_id?: string;
49
+ message?: OneBot12Segment[];
50
+ alt_message?: string;
51
+ user_id?: string;
52
+ group_id?: string;
53
+ channel_id?: string;
54
+ guild_id?: string;
55
+ [key: string]: unknown;
56
+ }
57
+ /** 消息段 */
58
+ export interface OneBot12Segment {
59
+ type: string;
60
+ data?: Record<string, unknown>;
61
+ }
62
+ /** 动作请求(应用发给实现) */
63
+ export interface OneBot12ActionRequest {
64
+ action: string;
65
+ params: Record<string, unknown>;
66
+ echo?: string;
67
+ self?: OneBot12Self;
68
+ }
69
+ /** 动作响应(实现返回给应用) */
70
+ export interface OneBot12ActionResponse {
71
+ status: 'ok' | 'failed';
72
+ retcode: number;
73
+ data?: unknown;
74
+ message: string;
75
+ echo?: string;
76
+ }
77
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,6DAA6D;AAC7D,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,yCAAyC;AACzC,MAAM,WAAW,gBAAiB,SAAQ,kBAAkB;IAC1D,UAAU,EAAE,IAAI,CAAC;IACjB,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,gDAAgD;AAChD,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,UAAU,EAAE,SAAS,CAAC;IACtB,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,2CAA2C;AAC3C,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,UAAU,EAAE,KAAK,CAAC;IAClB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG,qBAAqB,GAAG,iBAAiB,CAAC;AAE7F,4BAA4B;AAC5B,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,kBAAkB;AAClB,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU;AACV,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,mBAAmB;AACnB,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,oBAAoB;AACpB,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,IAAI,GAAG,QAAQ,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
package/lib/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * OneBot 12 适配器类型(参考 https://12.onebot.dev/ )
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/lib/utils.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * OneBot 12 事件与 zhin Message 的转换、消息段转换
3
+ */
4
+ import type { SendContent } from 'zhin.js';
5
+ import type { OneBot12Event, OneBot12Segment } from './types.js';
6
+ /** 判断是否为消息事件(type=message) */
7
+ export declare function isMessageEvent(ev: OneBot12Event): ev is OneBot12Event & {
8
+ message_id: string;
9
+ message?: OneBot12Segment[];
10
+ };
11
+ /** 从事件得到 zhin 场景 id:私聊 user_id,群 group_id,频道 channel_id 或 guild_id:channel_id */
12
+ export declare function getChannelId(ev: OneBot12Event): string;
13
+ /** 从事件得到 channel 类型 */
14
+ export declare function getChannelType(ev: OneBot12Event): 'private' | 'group';
15
+ /** 将 OneBot 12 消息事件转为 zhin Message 的 MessageBase 所需字段 */
16
+ export declare function formatOneBot12MessagePayload(ev: OneBot12Event, botName: string, recallFn: (msgId: string) => Promise<void>, replyFn: (channel: {
17
+ id: string;
18
+ type: 'group' | 'private';
19
+ }, content: (string | {
20
+ type: string;
21
+ data?: Record<string, unknown>;
22
+ })[], quote?: boolean | string) => Promise<string>): {
23
+ $id: string;
24
+ $adapter: 'onebot12';
25
+ $bot: string;
26
+ $channel: {
27
+ id: string;
28
+ type: 'group' | 'private';
29
+ };
30
+ $sender: {
31
+ id: string;
32
+ name: string;
33
+ };
34
+ $content: Array<{
35
+ type: string;
36
+ data: Record<string, unknown>;
37
+ }>;
38
+ $raw: string;
39
+ $timestamp: number;
40
+ $recall: () => Promise<void>;
41
+ $reply: (content: SendContent, quote?: boolean | string) => Promise<string>;
42
+ };
43
+ /** 将 zhin 的 content(segment 数组或字符串)转为 OneBot 12 message 段数组;简单实现仅 text */
44
+ export declare function contentToOb12Segments(content: SendContent): OneBot12Segment[];
45
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEjE,8BAA8B;AAC9B,wBAAgB,cAAc,CAAC,EAAE,EAAE,aAAa,GAAG,EAAE,IAAI,aAAa,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,EAAE,CAAA;CAAE,CAE3H;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,CAOtD;AAED,uBAAuB;AACvB,wBAAgB,cAAc,CAAC,EAAE,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAGrE;AAED,yDAAyD;AACzD,wBAAgB,4BAA4B,CAC1C,EAAE,EAAE,aAAa,EACjB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EAC1C,OAAO,EAAE,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,EAAE,OAAO,EAAE,CAAC,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GACjL;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,UAAU,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAA;KAAE,CAAC;IACpD,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7E,CA2BA;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,eAAe,EAAE,CAY7E"}
package/lib/utils.js ADDED
@@ -0,0 +1,60 @@
1
+ /** 判断是否为消息事件(type=message) */
2
+ export function isMessageEvent(ev) {
3
+ return ev.type === 'message' && !!ev.message_id;
4
+ }
5
+ /** 从事件得到 zhin 场景 id:私聊 user_id,群 group_id,频道 channel_id 或 guild_id:channel_id */
6
+ export function getChannelId(ev) {
7
+ if (ev.detail_type === 'private' && ev.user_id)
8
+ return ev.user_id;
9
+ if (ev.detail_type === 'group' && ev.group_id)
10
+ return ev.group_id;
11
+ if (ev.detail_type === 'channel' && ev.channel_id) {
12
+ return ev.guild_id ? `${ev.guild_id}:${ev.channel_id}` : ev.channel_id;
13
+ }
14
+ return '';
15
+ }
16
+ /** 从事件得到 channel 类型 */
17
+ export function getChannelType(ev) {
18
+ if (ev.detail_type === 'private')
19
+ return 'private';
20
+ return 'group';
21
+ }
22
+ /** 将 OneBot 12 消息事件转为 zhin Message 的 MessageBase 所需字段 */
23
+ export function formatOneBot12MessagePayload(ev, botName, recallFn, replyFn) {
24
+ const channelId = getChannelId(ev);
25
+ const channelType = getChannelType(ev);
26
+ const raw = ev.alt_message ?? (Array.isArray(ev.message) ? ev.message.map((s) => (s.type === 'text' ? s.data?.text ?? '' : '')).join('') : '');
27
+ const content = Array.isArray(ev.message)
28
+ ? ev.message.map((s) => ({ type: s.type, data: (s.data ?? {}) }))
29
+ : [{ type: 'text', data: { text: raw } }];
30
+ const senderId = ev.user_id ?? '';
31
+ const senderName = ev['user.name'] ?? ev['qq.nickname'] ?? senderId;
32
+ return {
33
+ $id: ev.message_id,
34
+ $adapter: 'onebot12',
35
+ $bot: botName,
36
+ $channel: { id: channelId, type: channelType },
37
+ $sender: { id: senderId, name: senderName },
38
+ $content: content,
39
+ $raw: raw,
40
+ $timestamp: ev.time ?? 0,
41
+ $recall: () => recallFn(ev.message_id),
42
+ $reply: (cnt, quote) => replyFn({ id: channelId, type: channelType }, (Array.isArray(cnt) ? cnt : [cnt]), quote),
43
+ };
44
+ }
45
+ /** 将 zhin 的 content(segment 数组或字符串)转为 OneBot 12 message 段数组;简单实现仅 text */
46
+ export function contentToOb12Segments(content) {
47
+ const arr = Array.isArray(content) ? content : [content];
48
+ const segs = [];
49
+ for (const c of arr) {
50
+ if (typeof c === 'string') {
51
+ segs.push({ type: 'text', data: { text: c } });
52
+ }
53
+ else if (c && typeof c === 'object' && 'type' in c) {
54
+ const el = c;
55
+ segs.push({ type: el.type, data: el.data ?? {} });
56
+ }
57
+ }
58
+ return segs.length ? segs : [{ type: 'text', data: { text: '' } }];
59
+ }
60
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@zhin.js/adapter-onebot12",
3
+ "version": "0.0.0",
4
+ "description": "Zhin.js adapter for OneBot 12 protocol",
5
+ "type": "module",
6
+ "main": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/index.d.ts",
11
+ "import": "./lib/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "lib",
16
+ "src",
17
+ "README.md"
18
+ ],
19
+ "keywords": [
20
+ "zhin",
21
+ "bot",
22
+ "adapter",
23
+ "onebot",
24
+ "onebot12",
25
+ "chatbot"
26
+ ],
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "ws": "^8.18.3"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^24.3.0",
33
+ "@types/ws": "^8.18.1",
34
+ "typescript": "^5.3.0",
35
+ "zhin.js": "1.0.50"
36
+ },
37
+ "peerDependencies": {
38
+ "zhin.js": "1.0.50",
39
+ "@zhin.js/http": "1.0.44"
40
+ },
41
+ "peerDependenciesMeta": {
42
+ "@zhin.js/http": {
43
+ "optional": true
44
+ }
45
+ },
46
+ "scripts": {
47
+ "build": "tsc && (test -f ../../services/console/lib/bin.js && node ../../services/console/lib/bin.js build || echo 'Skipping client build: console not built yet')",
48
+ "clean": "rimraf lib"
49
+ }
50
+ }
package/src/adapter.ts ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * OneBot 12 适配器:单一适配器支持正向 WS / Webhook / 反向 WS,由 config.connection 区分
3
+ * 协议文档:https://12.onebot.dev/
4
+ */
5
+ import type { Router } from '@zhin.js/http';
6
+ import { Adapter, Plugin } from 'zhin.js';
7
+ import { OneBot12WsClient } from './bot-ws.js';
8
+ import { OneBot12WebhookBot } from './bot-webhook.js';
9
+ import { OneBot12WssServer } from './bot-wss.js';
10
+ import type {
11
+ OneBot12BotConfig,
12
+ OneBot12WsConfig,
13
+ OneBot12WebhookConfig,
14
+ OneBot12WssConfig,
15
+ } from './types.js';
16
+
17
+ export type OneBot12Bot = OneBot12WsClient | OneBot12WebhookBot | OneBot12WssServer;
18
+
19
+ export class OneBot12Adapter extends Adapter<OneBot12Bot> {
20
+ #router?: Router;
21
+
22
+ constructor(plugin: Plugin) {
23
+ super(plugin, 'onebot12', []);
24
+ }
25
+
26
+ createBot(config: OneBot12BotConfig): OneBot12Bot {
27
+ switch (config.connection) {
28
+ case 'ws':
29
+ return new OneBot12WsClient(this, config as OneBot12WsConfig);
30
+ case 'webhook':
31
+ if (!this.#router) {
32
+ throw new Error('OneBot12 connection: webhook 需要 router,请安装并在配置中启用 @zhin.js/http');
33
+ }
34
+ return new OneBot12WebhookBot(this, this.#router, config as OneBot12WebhookConfig);
35
+ case 'wss':
36
+ if (!this.#router) {
37
+ throw new Error('OneBot12 connection: wss 需要 router,请安装并在配置中启用 @zhin.js/http');
38
+ }
39
+ return new OneBot12WssServer(this, this.#router, config as OneBot12WssConfig);
40
+ default:
41
+ throw new Error(`Unknown OneBot12 connection: ${(config as OneBot12BotConfig).connection}`);
42
+ }
43
+ }
44
+
45
+ async start(): Promise<void> {
46
+ this.#router = (this.plugin.inject as (key: string) => Router | undefined)('router');
47
+ (this.plugin.useContext as (key: string, fn: (router: Router) => void) => void)('router', (router: Router) => {
48
+ this.#router = router;
49
+ });
50
+ await super.start();
51
+ }
52
+ }
package/src/api.ts ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * OneBot 12 HTTP 动作调用:POST 动作请求到实现的 HTTP 端点,返回动作响应
3
+ * 参考 https://12.onebot.dev/connect/communication/http/
4
+ */
5
+ import type { OneBot12ActionRequest, OneBot12ActionResponse } from './types.js';
6
+
7
+ export interface OneBot12HttpOptions {
8
+ url: string;
9
+ access_token?: string;
10
+ }
11
+
12
+ /**
13
+ * 向 OneBot 实现发送动作请求(HTTP POST),返回动作响应
14
+ */
15
+ export async function callOneBot12Action(
16
+ options: OneBot12HttpOptions,
17
+ action: string,
18
+ params: Record<string, unknown> = {},
19
+ echo?: string,
20
+ ): Promise<OneBot12ActionResponse> {
21
+ const headers: Record<string, string> = { 'Content-Type': 'application/json' };
22
+ if (options.access_token) {
23
+ headers['Authorization'] = `Bearer ${options.access_token}`;
24
+ }
25
+ const body: OneBot12ActionRequest = { action, params };
26
+ if (echo) body.echo = echo;
27
+
28
+ const res = await fetch(options.url, {
29
+ method: 'POST',
30
+ headers,
31
+ body: JSON.stringify(body),
32
+ });
33
+
34
+ const text = await res.text();
35
+ if (res.status === 401) throw new Error(`OneBot12 鉴权失败: ${text}`);
36
+ if (res.status !== 200) throw new Error(`OneBot12 HTTP ${res.status}: ${text}`);
37
+
38
+ let data: OneBot12ActionResponse;
39
+ try {
40
+ data = JSON.parse(text) as OneBot12ActionResponse;
41
+ } catch {
42
+ throw new Error(`OneBot12 无效响应: ${text.slice(0, 200)}`);
43
+ }
44
+ if (data.status === 'failed' && data.retcode !== 0) {
45
+ throw new Error(`OneBot12 动作失败 retcode=${data.retcode}: ${data.message}`);
46
+ }
47
+ return data;
48
+ }