@alemonjs/onebot 0.2.8 → 2.1.0-alpha.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,3 @@
1
+ declare const platform = "onebot";
2
+
3
+ export { platform };
package/lib/config.js ADDED
@@ -0,0 +1,9 @@
1
+ import { getConfigValue } from 'alemonjs';
2
+
3
+ const platform = 'onebot';
4
+ const getOneBotConfig = () => {
5
+ const value = getConfigValue() || {};
6
+ return value[platform] || {};
7
+ };
8
+
9
+ export { getOneBotConfig, platform };
package/lib/index.d.ts CHANGED
@@ -1,10 +1,6 @@
1
- import * as alemonjs from 'alemonjs';
2
- import { OneBotClient } from './sdk/wss.js';
1
+ export { platform } from './config.js';
2
+ export { OneBotAPI as API } from './sdk/api.js';
3
3
 
4
- type Client = typeof OneBotClient.prototype;
5
- declare const client: Client;
6
- declare const platform = "onebot";
7
- declare const _default: alemonjs.DefinePlatformValue;
4
+ declare const _default: () => void;
8
5
 
9
- export { client, _default as default, platform };
10
- export type { Client };
6
+ export { _default as default };
package/lib/index.js CHANGED
@@ -1,29 +1,14 @@
1
- import { getConfigValue, useUserHashKey, onProcessor, createResult, ResultCode } from 'alemonjs';
1
+ import { cbpPlatform, useUserHashKey, createResult, ResultCode } from 'alemonjs';
2
+ import { getBufferByURL } from 'alemonjs/utils';
2
3
  import { OneBotClient } from './sdk/wss.js';
3
4
  import { readFileSync } from 'fs';
5
+ import { getOneBotConfig, platform } from './config.js';
6
+ export { OneBotAPI as API } from './sdk/api.js';
4
7
 
5
8
  const MyBot = {
6
9
  id: ''};
7
- const ImageURLToBuffer = async (url) => {
8
- const arrayBuffer = await fetch(url).then(res => res.arrayBuffer());
9
- return Buffer.from(arrayBuffer);
10
- };
11
- const client = new Proxy({}, {
12
- get: (_, prop) => {
13
- if (prop in global.client) {
14
- const original = global.client[prop];
15
- // 防止函数内this丢失
16
- return typeof original === 'function' ? original.bind(global.client) : original;
17
- }
18
- return undefined;
19
- }
20
- });
21
- const platform = 'onebot';
22
- var index = definePlatform(() => {
23
- let value = getConfigValue();
24
- if (!value)
25
- value = {};
26
- const config = value[platform];
10
+ var index = () => {
11
+ const config = getOneBotConfig();
27
12
  const client = new OneBotClient({
28
13
  // url
29
14
  url: config?.url ?? '',
@@ -35,6 +20,20 @@ var index = definePlatform(() => {
35
20
  reverse_port: config?.reverse_port ?? 17158
36
21
  });
37
22
  client.connect();
23
+ const url = `ws://127.0.0.1:${process.env?.port || config?.port || 17117}`;
24
+ const cbp = cbpPlatform(url);
25
+ const createUserAvatar = (id) => {
26
+ return `https://q1.qlogo.cn/g?b=qq&s=0&nk=${id}`;
27
+ };
28
+ const getMessageText = (message) => {
29
+ let msg = '';
30
+ for (const item of message) {
31
+ if (item.type == 'text') {
32
+ msg += item.data.text;
33
+ }
34
+ }
35
+ return msg.trim();
36
+ };
38
37
  client.on('META', event => {
39
38
  if (event?.self_id) {
40
39
  MyBot.id = String(event.self_id);
@@ -42,92 +41,41 @@ var index = definePlatform(() => {
42
41
  });
43
42
  client.on('MESSAGES', event => {
44
43
  const uis = config?.master_id ?? [];
45
- let msg = '';
46
- const arr = [];
47
- for (const item of event.message) {
48
- if (item.type == 'text') {
49
- msg = item.data.text;
50
- }
51
- }
52
- for (const item of arr) {
53
- msg = msg.replace(item.text, '').trim();
54
- }
55
- const url = `https://q1.qlogo.cn/g?b=qq&s=0&nk=${event.user_id}`;
56
- const UserAvatar = {
57
- toBuffer: async () => {
58
- const arrayBuffer = await fetch(url).then(res => res.arrayBuffer());
59
- return Buffer.from(arrayBuffer);
60
- },
61
- toBase64: async () => {
62
- const arrayBuffer = await fetch(url).then(res => res.arrayBuffer());
63
- return Buffer.from(arrayBuffer).toString('base64');
64
- },
65
- toURL: async () => {
66
- return url;
67
- }
68
- };
44
+ const msg = getMessageText(event.message);
69
45
  const UserId = String(event.user_id);
46
+ const UserAvatar = createUserAvatar(UserId);
70
47
  const UserKey = useUserHashKey({
71
48
  Platform: platform,
72
49
  UserId
73
50
  });
51
+ const groupId = String(event.group_id);
74
52
  // 定义消
75
53
  const e = {
76
54
  name: 'message.create',
77
- // 平台类型
78
55
  Platform: platform,
79
- // 频道
80
- GuildId: String(event.group_id),
81
- // 子频道
82
- ChannelId: String(event.group_id),
83
- IsMaster: uis.includes(String(event.user_id)),
56
+ GuildId: groupId,
57
+ ChannelId: groupId,
58
+ IsMaster: uis.includes(UserId),
59
+ SpaceId: groupId,
84
60
  IsBot: false,
85
61
  UserId: UserId,
86
62
  UserName: event.sender.nickname,
87
63
  UserKey,
88
64
  UserAvatar: UserAvatar,
89
- // message
90
65
  MessageId: String(event.message_id),
91
66
  MessageText: msg.trim(),
92
- // 用户openId
93
- OpenId: String(event.user_id),
94
- // 创建时间
67
+ OpenId: UserId,
95
68
  CreateAt: Date.now(),
96
- // 标签
97
69
  tag: 'message.create',
98
- //
99
- value: null
70
+ value: event
100
71
  };
101
- // 处理消息
102
- onProcessor('message.create', e, event);
72
+ cbp.send(e);
103
73
  });
104
74
  client.on('DIRECT_MESSAGE', event => {
105
75
  const uis = config?.master_id ?? [];
106
- let msg = '';
107
- const arr = [];
108
- for (const item of event.message) {
109
- if (item.type == 'text') {
110
- msg = item.data.text;
111
- }
112
- }
113
- for (const item of arr) {
114
- msg = msg.replace(item.text, '').trim();
115
- }
116
- const url = `https://q1.qlogo.cn/g?b=qq&s=0&nk=${event.user_id}`;
117
- const UserAvatar = {
118
- toBuffer: async () => {
119
- const arrayBuffer = await fetch(url).then(res => res.arrayBuffer());
120
- return Buffer.from(arrayBuffer);
121
- },
122
- toBase64: async () => {
123
- const arrayBuffer = await fetch(url).then(res => res.arrayBuffer());
124
- return Buffer.from(arrayBuffer).toString('base64');
125
- },
126
- toURL: async () => {
127
- return url;
128
- }
129
- };
76
+ const msg = getMessageText(event.message);
130
77
  const UserId = String(event.user_id);
78
+ const UserAvatar = createUserAvatar(UserId);
131
79
  const UserKey = useUserHashKey({
132
80
  Platform: platform,
133
81
  UserId
@@ -135,95 +83,85 @@ var index = definePlatform(() => {
135
83
  // 定义消
136
84
  const e = {
137
85
  name: 'private.message.create',
138
- // 平台类型
139
86
  Platform: platform,
140
- // 频道
141
- // GuildId: String(event.group_id),
142
- // 子频道
143
- // ChannelId: String(event.group_id),
144
87
  IsMaster: uis.includes(String(event.user_id)),
145
88
  IsBot: false,
146
89
  UserId: UserId,
147
90
  UserName: event.sender.nickname,
148
91
  UserKey,
149
92
  UserAvatar: UserAvatar,
150
- // message
151
93
  MessageId: String(event.message_id),
152
94
  MessageText: msg.trim(),
153
- // 用户openId
154
95
  OpenId: String(event.user_id),
155
- // 创建时间
156
96
  CreateAt: Date.now(),
157
- // 标签
158
97
  tag: 'private.message.create',
159
- //
160
- value: null
98
+ value: event
161
99
  };
162
- // 处理消息
163
- onProcessor('private.message.create', e, event);
100
+ cbp.send(e);
164
101
  });
165
102
  // 错误处理
166
103
  client.on('ERROR', event => {
167
- console.error('ERROR', event);
104
+ logger.error(event);
168
105
  });
169
- global.client = client;
170
106
  const sendGroup = async (event, val) => {
171
107
  if (val.length < 0)
172
- return Promise.all([]);
108
+ return [];
173
109
  const content = val
174
110
  .filter(item => item.type == 'Mention' || item.type == 'Text')
175
111
  .map(item => item.value)
176
112
  .join('');
177
- if (content) {
178
- return Promise.all([content].map(item => {
179
- client.sendGroupMessage({
113
+ try {
114
+ if (content) {
115
+ const res = await client.sendGroupMessage({
180
116
  group_id: event.ChannelId,
181
117
  message: [
182
118
  {
183
119
  type: 'text',
184
120
  data: {
185
- text: item
121
+ text: content
186
122
  }
187
123
  }
188
124
  ]
189
125
  });
190
- return createResult(ResultCode.Ok, 'client.groupOpenMessages', {
191
- id: null
192
- });
193
- }));
194
- }
195
- const images = val.filter(item => item.type == 'Image' || item.type == 'ImageFile' || item.type == 'ImageURL');
196
- if (images) {
197
- return Promise.all(images.map(async (item) => {
198
- let data = null;
199
- if (item.type === 'ImageFile') {
200
- const db = readFileSync(item.value);
201
- data = db;
202
- }
203
- else if (item.type === 'ImageURL') {
204
- const db = await ImageURLToBuffer(item.value);
205
- data = db;
206
- }
207
- else {
208
- data = item.value;
209
- }
210
- client.sendGroupMessage({
211
- group_id: event.ChannelId,
212
- message: [
213
- {
214
- type: 'image',
215
- data: {
216
- file: `base64://${data.toString('base64')}`
126
+ return [createResult(ResultCode.Ok, 'client.groupOpenMessages', res)];
127
+ }
128
+ const images = val.filter(item => item.type == 'Image' || item.type == 'ImageFile' || item.type == 'ImageURL');
129
+ if (images) {
130
+ return Promise.all(images.map(async (item) => {
131
+ let data = null;
132
+ if (item.type === 'ImageFile') {
133
+ const db = readFileSync(item.value);
134
+ data = db;
135
+ }
136
+ else if (item.type === 'ImageURL') {
137
+ const db = await getBufferByURL(item.value);
138
+ data = db;
139
+ }
140
+ else {
141
+ // data = item.value
142
+ data = Buffer.from(item.value, 'base64');
143
+ }
144
+ client.sendGroupMessage({
145
+ group_id: event.ChannelId,
146
+ message: [
147
+ {
148
+ type: 'image',
149
+ data: {
150
+ file: `base64://${data.toString('base64')}`
151
+ }
217
152
  }
218
- }
219
- ]
220
- });
221
- return createResult(ResultCode.Ok, 'client.groupOpenMessages', {
222
- id: null
223
- });
224
- }));
153
+ ]
154
+ });
155
+ return createResult(ResultCode.Ok, 'client.groupOpenMessages', {
156
+ id: null
157
+ });
158
+ }));
159
+ }
160
+ }
161
+ catch (error) {
162
+ return [createResult(ResultCode.Fail, 'client.groupOpenMessages', error)];
225
163
  }
226
- return Promise.all([]);
164
+ return [];
227
165
  };
228
166
  /**
229
167
  *
@@ -238,134 +176,151 @@ var index = definePlatform(() => {
238
176
  .filter(item => item.type == 'Link' || item.type == 'Mention' || item.type == 'Text')
239
177
  .map(item => item.value)
240
178
  .join('');
241
- if (content) {
242
- return Promise.all([content].map(item => {
243
- client.sendGroupMessage({
244
- group_id: event.ChannelId,
179
+ try {
180
+ if (content) {
181
+ const res = await client.sendPrivateMessage({
182
+ user_id: event.UserId,
245
183
  message: [
246
184
  {
247
185
  type: 'text',
248
186
  data: {
249
- text: item
187
+ text: content
250
188
  }
251
189
  }
252
190
  ]
253
191
  });
254
- return createResult(ResultCode.Ok, 'client.groupOpenMessages', {
255
- id: null
256
- });
257
- })).catch(err => [
258
- createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)
259
- ]);
260
- }
261
- const images = val.filter(item => item.type == 'Image' || item.type == 'ImageFile' || item.type == 'ImageURL');
262
- if (images) {
263
- return Promise.all(images.map(async (item) => {
264
- let data = null;
265
- if (item.type === 'ImageFile') {
266
- const db = readFileSync(item.value);
267
- data = db;
268
- }
269
- else if (item.type === 'ImageURL') {
270
- const db = await ImageURLToBuffer(item.value);
271
- data = db;
272
- }
273
- else {
274
- data = item.value;
275
- }
276
- client.sendGroupMessage({
277
- group_id: event.ChannelId,
278
- message: [
279
- {
280
- type: 'image',
281
- data: {
282
- file: `base64://${data.toString('base64')}`
192
+ return [createResult(ResultCode.Ok, 'client.sendPrivateMessage', res)];
193
+ }
194
+ const images = val.filter(item => item.type == 'Image' || item.type == 'ImageFile' || item.type == 'ImageURL');
195
+ if (images) {
196
+ return Promise.all(images.map(async (item) => {
197
+ let data = null;
198
+ if (item.type === 'ImageFile') {
199
+ const db = readFileSync(item.value);
200
+ data = db;
201
+ }
202
+ else if (item.type === 'ImageURL') {
203
+ const db = await getBufferByURL(item.value);
204
+ data = db;
205
+ }
206
+ else {
207
+ // data = item.value
208
+ data = Buffer.from(item.value, 'base64');
209
+ }
210
+ client.sendPrivateMessage({
211
+ user_id: event.UserId,
212
+ message: [
213
+ {
214
+ type: 'image',
215
+ data: {
216
+ file: `base64://${data.toString('base64')}`
217
+ }
283
218
  }
284
- }
285
- ]
286
- });
287
- return createResult(ResultCode.Ok, 'client.groupOpenMessages', {
288
- id: null
289
- });
290
- })).catch(err => [
291
- createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)
292
- ]);
219
+ ]
220
+ });
221
+ return createResult(ResultCode.Ok, 'client.sendPrivateMessage', {
222
+ id: null
223
+ });
224
+ }));
225
+ }
293
226
  }
294
- return Promise.all([]);
227
+ catch (error) {
228
+ return [createResult(ResultCode.Fail, 'client.sendPrivateMessage', error)];
229
+ }
230
+ return [];
295
231
  };
296
- return {
297
- platform,
298
- api: {
299
- active: {
300
- send: {
301
- channel: (event, val) => {
302
- return sendGroup(event, val);
303
- },
304
- user: (event, val) => {
305
- return sendPrivate(event, val);
306
- }
232
+ const api = {
233
+ active: {
234
+ send: {
235
+ channel: (event, val) => {
236
+ return sendGroup(event, val);
237
+ },
238
+ user: (event, val) => {
239
+ return sendPrivate(event, val);
307
240
  }
308
- },
309
- use: {
310
- send: (event, val) => {
311
- if (val.length < 0)
312
- return Promise.all([]);
313
- if (event['name'] == 'private.message.create') {
314
- return sendPrivate(event, val);
315
- }
316
- else if (event['name'] == 'message.create') {
317
- return sendGroup(event, val);
318
- }
241
+ }
242
+ },
243
+ use: {
244
+ send: (event, val) => {
245
+ if (val.length < 0)
319
246
  return Promise.all([]);
320
- },
321
- mention: async (event) => {
322
- const uis = config?.master_id ?? [];
323
- const e = event.value;
324
- if (event['name'] == 'message.create' || event['name'] == 'private.message.create') {
325
- const Metions = [];
326
- for (const item of e.message) {
327
- if (item.type == 'at') {
328
- let isBot = false;
329
- const uid = String(item.data.qq);
330
- if (uid == 'all') {
331
- continue;
332
- }
333
- if (uid == MyBot.id) {
334
- isBot = true;
335
- }
336
- const avatar = `https://q1.qlogo.cn/g?b=qq&s=0&nk=${uid}`;
337
- Metions.push({
338
- UserId: uid,
339
- UserKey: useUserHashKey({
340
- Platform: platform,
341
- UserId: uid
342
- }),
343
- UserName: item.data?.nickname,
344
- UserAvatar: {
345
- toBuffer: async () => {
346
- const arrayBuffer = await fetch(avatar).then(res => res.arrayBuffer());
347
- return Buffer.from(arrayBuffer);
348
- },
349
- toBase64: async () => {
350
- const arrayBuffer = await fetch(avatar).then(res => res.arrayBuffer());
351
- return Buffer.from(arrayBuffer).toString('base64');
352
- },
353
- toURL: async () => {
354
- return avatar;
355
- }
356
- },
357
- IsMaster: uis.includes(uid),
358
- IsBot: isBot
359
- });
247
+ if (event['name'] == 'private.message.create') {
248
+ return sendPrivate(event, val);
249
+ }
250
+ else if (event['name'] == 'message.create') {
251
+ return sendGroup(event, val);
252
+ }
253
+ return Promise.all([]);
254
+ },
255
+ mention: async (event) => {
256
+ const uis = config?.master_id ?? [];
257
+ const e = event.value;
258
+ if (event['name'] == 'message.create' || event['name'] == 'private.message.create') {
259
+ const Metions = [];
260
+ for (const item of e.message) {
261
+ if (item.type == 'at') {
262
+ let isBot = false;
263
+ const uid = String(item.data.qq);
264
+ if (uid == 'all') {
265
+ continue;
266
+ }
267
+ if (uid == MyBot.id) {
268
+ isBot = true;
360
269
  }
270
+ const avatar = createUserAvatar(uid);
271
+ Metions.push({
272
+ UserId: uid,
273
+ UserKey: useUserHashKey({
274
+ Platform: platform,
275
+ UserId: uid
276
+ }),
277
+ UserName: item.data?.nickname,
278
+ UserAvatar: avatar,
279
+ IsMaster: uis.includes(uid),
280
+ IsBot: isBot
281
+ });
361
282
  }
362
- return Metions;
363
283
  }
364
- return [];
284
+ return Metions;
365
285
  }
286
+ return [];
366
287
  }
367
288
  }
368
289
  };
369
- });
290
+ cbp.onactions(async (data, consume) => {
291
+ if (data.action === 'message.send') {
292
+ const event = data.payload.event;
293
+ const paramFormat = data.payload.params.format;
294
+ const res = await api.use.send(event, paramFormat);
295
+ consume(res);
296
+ }
297
+ else if (data.action === 'message.send.channel') {
298
+ const channel_id = data.payload.ChannelId;
299
+ const val = data.payload.params.format;
300
+ const res = await api.active.send.channel(channel_id, val);
301
+ consume(res);
302
+ }
303
+ else if (data.action === 'message.send.user') {
304
+ const user_id = data.payload.UserId;
305
+ const val = data.payload.params.format;
306
+ const res = await api.active.send.user(user_id, val);
307
+ consume(res);
308
+ }
309
+ else if (data.action === 'mention.get') {
310
+ const event = data.payload.event;
311
+ const res = await api.use.mention(event);
312
+ consume([createResult(ResultCode.Ok, '请求完成', res)]);
313
+ }
314
+ });
315
+ // 处理 api 调用
316
+ cbp.onapis(async (data, consume) => {
317
+ const key = data.payload?.key;
318
+ if (client[key]) {
319
+ const params = data.payload.params;
320
+ const res = await client[key](...params);
321
+ consume([createResult(ResultCode.Ok, '请求完成', res)]);
322
+ }
323
+ });
324
+ };
370
325
 
371
- export { client, index as default, platform };
326
+ export { index as default, platform };
@@ -0,0 +1,73 @@
1
+ import WebSocket from 'ws';
2
+
3
+ declare class OneBotAPI {
4
+ ws: WebSocket | null;
5
+ /**
6
+ * 发送私聊消息
7
+ * @param options
8
+ * @returns
9
+ */
10
+ sendPrivateMessage(options: {
11
+ user_id: number;
12
+ message: any[];
13
+ }): Promise<any>;
14
+ /**
15
+ * 发送群消息
16
+ * @param options
17
+ * @returns
18
+ */
19
+ sendGroupMessage(options: {
20
+ group_id: number;
21
+ message: any[];
22
+ }): Promise<any>;
23
+ /**
24
+ * 发送消息
25
+ * @param options
26
+ * @returns
27
+ */
28
+ sendMessage(options: {
29
+ message_type: 'private' | 'group';
30
+ group_id?: number;
31
+ user_id?: number;
32
+ message: any[];
33
+ }): Promise<any>;
34
+ /**
35
+ * 好友列表
36
+ */
37
+ getFriendList(): Promise<any>;
38
+ /**
39
+ * 群列表
40
+ */
41
+ getGroupList(): Promise<any>;
42
+ /**
43
+ * 群成员列表
44
+ * @param options
45
+ * @returns
46
+ */
47
+ getGroupMemberList(options: {
48
+ group_id: number;
49
+ }): Promise<any>;
50
+ /**
51
+ * 处理好友请求
52
+ * @param options
53
+ * @returns
54
+ */
55
+ setFriendAddRequest(options: {
56
+ flag: string;
57
+ approve: boolean;
58
+ remark?: string;
59
+ }): Promise<any>;
60
+ /**
61
+ * 处理群请求
62
+ * @param options
63
+ * @returns
64
+ */
65
+ setGroupAddRequest(options: {
66
+ flag: string;
67
+ sub_type: string;
68
+ approve: boolean;
69
+ reason?: string;
70
+ }): Promise<any>;
71
+ }
72
+
73
+ export { OneBotAPI };
package/lib/sdk/api.js ADDED
@@ -0,0 +1,158 @@
1
+ import { generateUniqueId, actionResolves, actionTimeouts, timeoutTime } from './config.js';
2
+
3
+ /**
4
+ *
5
+ * @param ws
6
+ * @param data
7
+ * @returns
8
+ */
9
+ const send = (ws, data) => {
10
+ const id = generateUniqueId();
11
+ // 设置唯一标识符
12
+ data.echo = id;
13
+ return new Promise((resolve, reject) => {
14
+ actionResolves.set(id, { resolve, reject });
15
+ // 发送消息
16
+ ws.send(JSON.stringify(data));
17
+ // 30 秒后超时
18
+ const timeout = setTimeout(() => {
19
+ // 被清理了
20
+ if (!actionResolves.has(id) || !actionTimeouts.has(id)) {
21
+ return;
22
+ }
23
+ // 删除回调
24
+ actionResolves.delete(id);
25
+ // 删除超时器
26
+ actionTimeouts.delete(id);
27
+ // 不会当错误进行处理。而是传入错误码
28
+ resolve(null);
29
+ }, timeoutTime);
30
+ actionTimeouts.set(id, timeout);
31
+ });
32
+ };
33
+ // 消费
34
+ const consume = (parsedMessage) => {
35
+ // 读取 唯一标识
36
+ const id = parsedMessage.echo;
37
+ const { resolve, reject } = actionResolves.get(id) || {};
38
+ actionResolves.delete(id);
39
+ // 清除超时器
40
+ const timeout = actionTimeouts.get(id);
41
+ if (timeout) {
42
+ actionTimeouts.delete(id);
43
+ clearTimeout(timeout);
44
+ }
45
+ if (!resolve || !reject) {
46
+ return;
47
+ }
48
+ if (![0, 1].includes(parsedMessage?.retcode)) {
49
+ reject(parsedMessage?.data);
50
+ return;
51
+ }
52
+ resolve(parsedMessage?.data);
53
+ };
54
+ class OneBotAPI {
55
+ ws = null;
56
+ /**
57
+ * 发送私聊消息
58
+ * @param options
59
+ * @returns
60
+ */
61
+ sendPrivateMessage(options) {
62
+ if (!this.ws)
63
+ return;
64
+ return send(this.ws, {
65
+ action: 'send_private_msg',
66
+ params: options
67
+ });
68
+ }
69
+ /**
70
+ * 发送群消息
71
+ * @param options
72
+ * @returns
73
+ */
74
+ sendGroupMessage(options) {
75
+ if (!this.ws)
76
+ return;
77
+ return send(this.ws, {
78
+ action: 'send_group_msg',
79
+ params: options
80
+ });
81
+ }
82
+ /**
83
+ * 发送消息
84
+ * @param options
85
+ * @returns
86
+ */
87
+ sendMessage(options) {
88
+ if (!this.ws)
89
+ return;
90
+ return send(this.ws, {
91
+ action: 'send_msg',
92
+ params: options
93
+ });
94
+ }
95
+ /**
96
+ * 好友列表
97
+ */
98
+ getFriendList() {
99
+ if (!this.ws)
100
+ return;
101
+ return send(this.ws, {
102
+ action: 'get_friend_list',
103
+ params: {}
104
+ });
105
+ }
106
+ /**
107
+ * 群列表
108
+ */
109
+ getGroupList() {
110
+ if (!this.ws)
111
+ return;
112
+ return send(this.ws, {
113
+ action: 'get_group_list',
114
+ params: {}
115
+ });
116
+ }
117
+ /**
118
+ * 群成员列表
119
+ * @param options
120
+ * @returns
121
+ */
122
+ getGroupMemberList(options) {
123
+ if (!this.ws)
124
+ return;
125
+ return send(this.ws, {
126
+ action: 'get_group_member_list',
127
+ params: options
128
+ });
129
+ }
130
+ /**
131
+ * 处理好友请求
132
+ * @param options
133
+ * @returns
134
+ */
135
+ setFriendAddRequest(options) {
136
+ if (!this.ws)
137
+ return;
138
+ return send(this.ws, {
139
+ action: 'set_friend_add_request',
140
+ params: options
141
+ });
142
+ }
143
+ /**
144
+ * 处理群请求
145
+ * @param options
146
+ * @returns
147
+ */
148
+ setGroupAddRequest(options) {
149
+ if (!this.ws)
150
+ return;
151
+ return send(this.ws, {
152
+ action: 'set_group_add_request',
153
+ params: options
154
+ });
155
+ }
156
+ }
157
+
158
+ export { OneBotAPI, consume };
@@ -0,0 +1,12 @@
1
+ // 行为回调
2
+ const actionResolves = new Map();
3
+ // 超时器
4
+ const actionTimeouts = new Map();
5
+ // 生成唯一标识符
6
+ const generateUniqueId = () => {
7
+ return Date.now().toString(36) + Math.random().toString(36).substring(2);
8
+ };
9
+ // 超时时间
10
+ const timeoutTime = 1000 * 12; // 12秒
11
+
12
+ export { actionResolves, actionTimeouts, generateUniqueId, timeoutTime };
package/lib/sdk/wss.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import WebSocket, { WebSocketServer } from 'ws';
2
- import { randomUUID } from 'crypto';
2
+ import { OneBotAPI, consume } from './api.js';
3
3
 
4
4
  /**
5
5
  * 连接
6
6
  */
7
- class OneBotClient {
7
+ class OneBotClient extends OneBotAPI {
8
8
  #options = {
9
9
  url: '',
10
10
  access_token: '',
@@ -16,16 +16,14 @@ class OneBotClient {
16
16
  * @param opstion
17
17
  */
18
18
  constructor(opstion) {
19
+ super();
19
20
  for (const key in opstion) {
20
21
  if (Object.prototype.hasOwnProperty.call(opstion, key)) {
21
22
  this.#options[key] = opstion[key];
22
23
  }
23
24
  }
24
25
  }
25
- #ws = null;
26
26
  #events = {};
27
- #echo = {};
28
- timeout = 30000;
29
27
  /**
30
28
  * 注册事件处理程序
31
29
  * @param key 事件名称
@@ -98,25 +96,9 @@ class OneBotClient {
98
96
  }
99
97
  return;
100
98
  }
101
- else if (event?.echo === 'get_friend_list' ||
102
- event?.echo === 'get_group_list' ||
103
- event?.echo === 'get_group_member_list') {
104
- // 处理获取好友列表和群列表的响应
105
- // if (this.#events['META']) this.#events['META'](event)
106
- // console.debug('响应', event)
107
- return;
108
- }
109
- if (!event?.post_type && event?.echo && this.#echo[event?.echo]) {
110
- if (![0, 1].includes(event?.retcode))
111
- this.#echo[event?.echo].reject(Object.assign(this.#echo[event?.echo].request, { error: event }));
112
- else
113
- this.#echo[event?.echo].resolve(event?.data
114
- ? new Proxy(event, {
115
- get: (target, prop) => target.event[prop] ?? target[prop]
116
- })
117
- : event);
118
- clearTimeout(this.#echo[event?.echo].timeout);
119
- delete this.#echo[event?.echo];
99
+ else if (event?.echo) {
100
+ // 消费
101
+ consume(event);
120
102
  }
121
103
  }
122
104
  catch (err) {
@@ -131,161 +113,32 @@ class OneBotClient {
131
113
  reason: reason.toString('utf8')
132
114
  });
133
115
  };
134
- if (!this.#ws) {
116
+ if (!this.ws) {
135
117
  if (reverse_enable) {
136
118
  // reverse_open
137
119
  const server = new WebSocketServer({ port: reverse_port ?? 17158 });
138
120
  server.on('connection', ws => {
139
- this.#ws = ws;
121
+ this.ws = ws;
140
122
  // message
141
- this.#ws.on('message', onMessage);
123
+ this.ws.on('message', onMessage);
142
124
  // close
143
- this.#ws.on('close', onClose);
125
+ this.ws.on('close', onClose);
144
126
  console.info('connected: ws://127.0.0.1:' + reverse_port);
145
127
  });
146
128
  }
147
129
  else {
148
130
  // forward_open
149
- this.#ws = new WebSocket(url, c);
150
- this.#ws.on('open', () => {
131
+ this.ws = new WebSocket(url, c);
132
+ this.ws.on('open', () => {
151
133
  console.debug(`open:${url}`);
152
134
  });
153
135
  // message
154
- this.#ws.on('message', onMessage);
136
+ this.ws.on('message', onMessage);
155
137
  // close
156
- this.#ws.on('close', onClose);
138
+ this.ws.on('close', onClose);
157
139
  }
158
140
  }
159
141
  }
160
- /**
161
- * 发送私聊消息
162
- * @param options
163
- * @returns
164
- */
165
- sendPrivateMessage(options) {
166
- if (!this.#ws)
167
- return;
168
- return this.#ws.send(JSON.stringify({
169
- action: 'send_private_msg',
170
- params: options,
171
- echo: randomUUID()
172
- }));
173
- }
174
- /**
175
- * 发送群消息
176
- * @param options
177
- * @returns
178
- */
179
- sendGroupMessage(options) {
180
- if (!this.#ws)
181
- return;
182
- return this.#ws.send(JSON.stringify({
183
- action: 'send_group_msg',
184
- params: options,
185
- echo: randomUUID()
186
- }));
187
- }
188
- /**
189
- * 发送消息
190
- * @param options
191
- * @returns
192
- */
193
- sendMessage(options) {
194
- if (!this.#ws)
195
- return;
196
- return this.#ws.send(JSON.stringify({
197
- action: 'send_msg',
198
- params: options,
199
- echo: randomUUID()
200
- }));
201
- }
202
- /**
203
- * 好友列表
204
- */
205
- getFriendList() {
206
- if (!this.#ws)
207
- return;
208
- return this.#ws.send(JSON.stringify({
209
- action: 'get_friend_list',
210
- params: {},
211
- echo: 'get_friend_list'
212
- }));
213
- }
214
- /**
215
- * 群列表
216
- */
217
- getGroupList() {
218
- if (!this.#ws)
219
- return;
220
- return this.#ws.send(JSON.stringify({
221
- action: 'get_group_list',
222
- params: {},
223
- echo: 'get_group_list'
224
- }));
225
- }
226
- /**
227
- * 群成员列表
228
- * @param options
229
- * @returns
230
- */
231
- getGroupMemberList(options) {
232
- if (!this.#ws)
233
- return;
234
- return this.#ws.send(JSON.stringify({
235
- action: 'get_group_member_list',
236
- params: options,
237
- echo: 'get_group_member_list'
238
- }));
239
- }
240
- /**
241
- * 处理好友请求
242
- * @param options
243
- * @returns
244
- */
245
- setFriendAddRequest(options) {
246
- if (!this.#ws)
247
- return;
248
- return this.#ws.send(JSON.stringify({
249
- action: 'set_friend_add_request',
250
- params: options,
251
- echo: randomUUID()
252
- }));
253
- }
254
- /**
255
- * 处理群请求
256
- * @param options
257
- * @returns
258
- */
259
- setGroupAddRequest(options) {
260
- if (!this.#ws)
261
- return;
262
- return this.#ws.send(JSON.stringify({
263
- action: 'set_group_add_request',
264
- params: options,
265
- echo: randomUUID()
266
- }));
267
- }
268
- /**
269
- * @param options
270
- * @returns
271
- */
272
- sendApi(options) {
273
- if (!this.#ws)
274
- return;
275
- if (!options.echo)
276
- options.echo = randomUUID();
277
- this.#ws.send(JSON.stringify(options));
278
- return new Promise((resolve, reject) => (this.#echo[options.echo] = {
279
- request: options,
280
- resolve,
281
- reject,
282
- timeout: setTimeout(() => {
283
- reject(Object.assign(options, { timeout: this.timeout }));
284
- delete this.#echo[options.echo];
285
- console.error('请求超时:', options);
286
- }, this.timeout)
287
- }));
288
- }
289
142
  }
290
143
 
291
144
  export { OneBotClient };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@alemonjs/onebot",
3
- "version": "0.2.8",
4
- "description": "onebot",
3
+ "version": "2.1.0-alpha.0",
4
+ "description": "onebot v11",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",
7
7
  "type": "module",
package/lib/sdk/type.d.ts DELETED
@@ -1,90 +0,0 @@
1
- interface Sender {
2
- user_id: number;
3
- nickname: string;
4
- card: string;
5
- role: 'admin' | 'member';
6
- }
7
- type Message = {
8
- type: 'image';
9
- data: {
10
- file: string;
11
- sub_type: number;
12
- file_id: string;
13
- url: string;
14
- file_size: string;
15
- file_unique: string;
16
- };
17
- } | {
18
- type: 'text';
19
- data: {
20
- text: string;
21
- };
22
- } | {
23
- type: 'json';
24
- data: string;
25
- } | {
26
- type: 'forward';
27
- data: {
28
- id: number;
29
- content: any[];
30
- };
31
- };
32
- interface MESSAGES_TYPE {
33
- self_id: number;
34
- user_id: number;
35
- time: number;
36
- message_id: number;
37
- message_seq: number;
38
- real_id: number;
39
- message_type: 'group';
40
- sender: Sender;
41
- raw_message: string;
42
- font: number;
43
- sub_type: 'normal';
44
- message: Message[];
45
- message_format: 'array';
46
- post_type: 'message';
47
- group_id: number;
48
- }
49
- interface DIRECT_MESSAGE_TYPE {
50
- self_id: number;
51
- user_id: number;
52
- time: number;
53
- message_id: number;
54
- message_seq: number;
55
- real_id: number;
56
- message_type: 'private';
57
- sender: {
58
- user_id: 1715713638;
59
- nickname: string;
60
- card: '';
61
- };
62
- raw_message: string;
63
- font: 14;
64
- sub_type: 'group' | 'friend';
65
- message: Message[];
66
- message_format: 'array';
67
- post_type: 'message';
68
- group_id: number;
69
- temp_source: number;
70
- }
71
- interface meta_event_lifecycle {
72
- time: number;
73
- self_id: number;
74
- post_type: 'meta_event';
75
- meta_event_type: 'lifecycle';
76
- sub_type: 'connect';
77
- }
78
- interface meta_event_heartbeat {
79
- time: number;
80
- self_id: number;
81
- post_type: 'meta_event';
82
- meta_event_type: 'heartbeat';
83
- status: {
84
- online: boolean;
85
- good: boolean;
86
- };
87
- interval: number;
88
- }
89
-
90
- export type { DIRECT_MESSAGE_TYPE, MESSAGES_TYPE, meta_event_heartbeat, meta_event_lifecycle };
package/lib/sdk/wss.d.ts DELETED
@@ -1,120 +0,0 @@
1
- import { DIRECT_MESSAGE_TYPE, MESSAGES_TYPE, meta_event_lifecycle, meta_event_heartbeat } from './type.js';
2
-
3
- type OneBotEventMap = {
4
- DIRECT_MESSAGE: DIRECT_MESSAGE_TYPE;
5
- MESSAGES: MESSAGES_TYPE;
6
- META: meta_event_lifecycle | meta_event_heartbeat;
7
- REQUEST_ADD_FRIEND: any;
8
- REQUEST_ADD_GROUP: any;
9
- NOTICE_GROUP_MEMBER_INCREASE: any;
10
- NOTICE_GROUP_MEMBER_REDUCE: any;
11
- ERROR: any;
12
- };
13
- /**
14
- * 连接
15
- */
16
- declare class OneBotClient {
17
- #private;
18
- /**
19
- * 设置配置
20
- * @param opstion
21
- */
22
- constructor(opstion: {
23
- url: string;
24
- access_token: string;
25
- reverse_enable: boolean;
26
- reverse_port: number;
27
- });
28
- timeout: number;
29
- /**
30
- * 注册事件处理程序
31
- * @param key 事件名称
32
- * @param val 事件处理函数
33
- */
34
- on<T extends keyof OneBotEventMap>(key: T, val: (event: OneBotEventMap[T]) => any): this;
35
- /**
36
- *
37
- * @param cfg
38
- * @param conversation
39
- */
40
- connect(): Promise<void>;
41
- /**
42
- * 发送私聊消息
43
- * @param options
44
- * @returns
45
- */
46
- sendPrivateMessage(options: {
47
- user_id: number;
48
- message: any[];
49
- }): void;
50
- /**
51
- * 发送群消息
52
- * @param options
53
- * @returns
54
- */
55
- sendGroupMessage(options: {
56
- group_id: number;
57
- message: any[];
58
- }): void;
59
- /**
60
- * 发送消息
61
- * @param options
62
- * @returns
63
- */
64
- sendMessage(options: {
65
- message_type: 'private' | 'group';
66
- group_id?: number;
67
- user_id?: number;
68
- message: any[];
69
- }): void;
70
- /**
71
- * 好友列表
72
- */
73
- getFriendList(): void;
74
- /**
75
- * 群列表
76
- */
77
- getGroupList(): void;
78
- /**
79
- * 群成员列表
80
- * @param options
81
- * @returns
82
- */
83
- getGroupMemberList(options: {
84
- group_id: number;
85
- }): void;
86
- /**
87
- * 处理好友请求
88
- * @param options
89
- * @returns
90
- */
91
- setFriendAddRequest(options: {
92
- flag: string;
93
- approve: boolean;
94
- remark?: string;
95
- }): void;
96
- /**
97
- * 处理群请求
98
- * @param options
99
- * @returns
100
- */
101
- setGroupAddRequest(options: {
102
- flag: string;
103
- sub_type: string;
104
- approve: boolean;
105
- reason?: string;
106
- }): void;
107
- /**
108
- * @param options
109
- * @returns
110
- */
111
- sendApi(options: {
112
- action: string;
113
- params?: {
114
- [key: string]: any;
115
- };
116
- echo?: string;
117
- }): Promise<unknown>;
118
- }
119
-
120
- export { OneBotClient };
@@ -1,73 +0,0 @@
1
- import Koa from 'koa'
2
- import Router from 'koa-router'
3
-
4
- // 使用koa + router 写 hello world
5
- const createServer = client => {
6
- const app = new Koa()
7
- const router = new Router()
8
- const port = 8080 // 端口号
9
- // 检测
10
- router.get('/', ctx => {
11
- ctx.body = 'Hello, World!'
12
- })
13
- // 获取群列表
14
- router.get('/get_group_list', async ctx => {
15
- client.getGroupList()
16
- ctx.body = 'Hello, World!'
17
- })
18
- // 获取好友列表
19
- router.get('/get_friend_list', async ctx => {
20
- client.getFriendList()
21
- ctx.body = 'Hello, World!'
22
- })
23
- // 获取群成员列表
24
- router.get('/get_group_member_list', async ctx => {
25
- const group_id = ctx.query.group_id
26
- if (!group_id) {
27
- ctx.status = 400
28
- ctx.body = 'group_id is required'
29
- return
30
- }
31
- client.getGroupMemberList({ group_id: Number(group_id) })
32
- ctx.body = 'Hello, World!'
33
- })
34
- // 同意加群
35
- router.get('/set_group_add_request', async ctx => {
36
- const flag = ctx.query.flag
37
- const sub_type = ctx.query.sub_type
38
- const approve = ctx.query.approve
39
- if (!flag || !sub_type || !approve) {
40
- ctx.status = 400
41
- ctx.body = 'flag, sub_type and approve are required'
42
- return
43
- }
44
- client.setGroupAddRequest({
45
- flag: String(flag),
46
- sub_type: String(sub_type),
47
- approve: Boolean(approve)
48
- })
49
- ctx.body = 'Hello, World!'
50
- })
51
- // 同意加好友
52
- router.get('/set_friend_add_request', async ctx => {
53
- const flag = ctx.query.flag
54
- const approve = ctx.query.approve
55
- if (!flag || !approve) {
56
- ctx.status = 400
57
- ctx.body = 'flag and approve are required'
58
- return
59
- }
60
- client.setFriendAddRequest({
61
- flag: String(flag),
62
- approve: Boolean(approve)
63
- })
64
- ctx.body = 'Hello, World!'
65
- })
66
- app.use(router.routes())
67
- app.use(router.allowedMethods())
68
- app.listen(port, () => {
69
- console.log(`Server is running at http://localhost:${port}`)
70
- })
71
- }
72
-
73
- export { createServer }