@alemonjs/qq-bot 0.0.1 → 0.0.2

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/lib/api.js CHANGED
@@ -23,30 +23,48 @@ class QQBotAPI {
23
23
  * @param url
24
24
  * @returns
25
25
  */
26
- getAuthentication(appId, clientSecret) {
26
+ getAuthentication(app_id, clientSecret) {
27
27
  return axios.post(`${this.BOTS_API_RUL}/app/getAppAccessToken`, {
28
- appId: appId,
28
+ appId: app_id,
29
29
  clientSecret: clientSecret
30
30
  });
31
31
  }
32
32
  /**
33
- * 创建axios实例
33
+ * group
34
34
  * @param config
35
35
  * @returns
36
36
  */
37
37
  async GroupService(options) {
38
- const appId = config.get('appId');
38
+ const app_id = config.get('app_id');
39
39
  const token = config.get('token');
40
40
  const service = await axios.create({
41
41
  baseURL: this.API_URL,
42
42
  timeout: 20000,
43
43
  headers: {
44
- 'X-Union-Appid': appId,
44
+ 'X-Union-Appid': app_id,
45
45
  'Authorization': `QQBot ${token}`
46
46
  }
47
47
  });
48
48
  return service(options);
49
49
  }
50
+ /**
51
+ * guild
52
+ * @param opstion
53
+ * @returns
54
+ */
55
+ async request(opstion) {
56
+ const app_id = config.get('app_id');
57
+ const token = config.get('token');
58
+ const sandbox = config.get('sandbox');
59
+ const service = await axios.create({
60
+ baseURL: sandbox ? this.API_URL_SANDBOX : this.BOTS_API_RUL,
61
+ timeout: 20000,
62
+ headers: {
63
+ Authorization: `Bot ${app_id}.${token}`
64
+ }
65
+ });
66
+ return service(opstion);
67
+ }
50
68
  /**
51
69
  * 得到鉴权
52
70
  * @returns
@@ -300,24 +318,6 @@ class QQBotAPI {
300
318
  method: 'delete'
301
319
  }).then(res => res?.data);
302
320
  }
303
- /**
304
- * 基础请求
305
- * @param opstion
306
- * @returns
307
- */
308
- async request(opstion) {
309
- const appId = config.get('appId');
310
- const token = config.get('token');
311
- const sandbox = config.get('sandbox');
312
- const service = await axios.create({
313
- baseURL: sandbox ? this.API_URL_SANDBOX : this.API_URL,
314
- timeout: 20000,
315
- headers: {
316
- Authorization: `Bot ${appId}.${token}`
317
- }
318
- });
319
- return service(opstion);
320
- }
321
321
  /**
322
322
  * 创建form
323
323
  * @param image
package/lib/client.js CHANGED
@@ -19,11 +19,16 @@ class QQBotClient extends QQBotAPI {
19
19
  */
20
20
  constructor(opstion) {
21
21
  super();
22
- config.set('secret', opstion.secret);
23
- config.set('appId', opstion.appId);
24
- config.set('token', opstion.token);
25
- config.set('port', opstion.port);
26
- config.set('ws', opstion.ws);
22
+ if (opstion.secret)
23
+ config.set('secret', opstion.secret);
24
+ if (opstion.app_id)
25
+ config.set('app_id', opstion.app_id);
26
+ if (opstion.token)
27
+ config.set('token', opstion.token);
28
+ if (opstion.port)
29
+ config.set('port', opstion.port);
30
+ if (opstion.ws)
31
+ config.set('ws', opstion.ws);
27
32
  }
28
33
  /**
29
34
  * 注册事件处理程序
@@ -42,134 +47,151 @@ class QQBotClient extends QQBotAPI {
42
47
  * @param cfg
43
48
  * @param conversation
44
49
  */
45
- async connect() {
46
- this.#app = new Koa();
47
- this.#app.use(bodyParser());
48
- const router = new Router();
49
- const port = config.get('port');
50
- const cfg = {
51
- secret: config.get('secret'),
52
- port: port ? Number(port) : 17157
53
- };
54
- const ntqqWebhook = new WebhookAPI({
55
- secret: 'YI2mWG0lWH2nYJ4qcOAwiUH4reRE1pdR'
56
- });
57
- this.#app.use(async (ctx, next) => {
58
- let rawData = '';
59
- ctx.req.on('data', chunk => (rawData += chunk));
60
- ctx.req.on('end', () => (ctx.request.rawBody = rawData));
61
- await next();
62
- });
63
- // 启动服务
64
- router.post('/webhook', async (ctx) => {
65
- const sign = ctx.req.headers['x-signature-ed25519'];
66
- const timestamp = ctx.req.headers['x-signature-timestamp'];
67
- const rawBody = ctx.request.rawBody;
68
- const isValid = ntqqWebhook.validSign(timestamp, rawBody, String(sign));
69
- if (!isValid) {
70
- ctx.status = 400;
71
- ctx.body = { msg: 'invalid signature' };
72
- return;
73
- }
74
- const body = ctx.request.body;
75
- if (body.op == 13) {
76
- ctx.status = 200;
77
- ctx.body = {
78
- // 返回明文 token
79
- plain_token: body.d.plain_token,
80
- // 生成签名
81
- signature: ntqqWebhook.getSign(body.d.event_ts, body.d.plain_token)
82
- };
83
- }
84
- else if (body.op == 0) {
85
- ctx.status = 204;
86
- console.log('body', body.d);
87
- // 根据事件类型,处理事件
88
- for (const event of this.#events[body.t] || []) {
89
- event(body.d);
50
+ connect() {
51
+ try {
52
+ this.#app = new Koa();
53
+ this.#app.use(bodyParser());
54
+ const router = new Router();
55
+ const port = config.get('port');
56
+ const secret = config.get('secret');
57
+ const cfg = {
58
+ secret: secret ?? '',
59
+ port: port ? Number(port) : 17157
60
+ };
61
+ const ntqqWebhook = new WebhookAPI({
62
+ secret: cfg.secret
63
+ });
64
+ this.#app.use(async (ctx, next) => {
65
+ let rawData = '';
66
+ ctx.req.on('data', chunk => (rawData += chunk));
67
+ ctx.req.on('end', () => (ctx.request.rawBody = rawData));
68
+ await next();
69
+ });
70
+ // 启动服务
71
+ router.post('/webhook', async (ctx) => {
72
+ const sign = ctx.req.headers['x-signature-ed25519'];
73
+ const timestamp = ctx.req.headers['x-signature-timestamp'];
74
+ const rawBody = ctx.request.rawBody;
75
+ const isValid = ntqqWebhook.validSign(timestamp, rawBody, String(sign));
76
+ if (!isValid) {
77
+ ctx.status = 400;
78
+ ctx.body = { msg: 'invalid signature' };
79
+ return;
90
80
  }
91
- // 也可以分法到客户端。 发送失败需要处理 或清理调
92
- for (const client of this.#client) {
93
- try {
94
- client.ws.send(JSON.stringify(body.d));
95
- }
96
- catch (error) {
97
- console.error('send error', error);
98
- }
81
+ const body = ctx.request.body;
82
+ if (body.op == 13) {
83
+ ctx.status = 200;
84
+ ctx.body = {
85
+ // 返回明文 token
86
+ plain_token: body.d.plain_token,
87
+ // 生成签名
88
+ signature: ntqqWebhook.getSign(body.d.event_ts, body.d.plain_token)
89
+ };
99
90
  }
100
- }
101
- });
102
- this.#app.use(router.routes());
103
- this.#app.use(router.allowedMethods());
104
- // 启动服务
105
- const server = this.#app.listen(cfg.port, () => {
106
- console.log('Server running at http://localhost:' + cfg.port + '/webhook');
107
- });
108
- // 创建 WebSocketServer 并监听同一个端口
109
- const wss = new WebSocketServer({ server: server });
110
- // 处理客户端连接
111
- wss.on('connection', ws => {
112
- const clientId = v4();
113
- ws['clientId'] = clientId;
114
- console.log(clientId, 'connection');
115
- this.#client.push({ id: clientId, ws });
116
- // 处理消息事件
117
- ws.on('message', (message) => {
118
- // 拿到消息
119
- try {
120
- const body = JSON.parse(message.toString());
91
+ else if (body.op == 0) {
92
+ ctx.status = 204;
93
+ console.log('body', body.d);
94
+ // 根据事件类型,处理事件
121
95
  for (const event of this.#events[body.t] || []) {
122
- event(body);
96
+ event(body.d);
97
+ }
98
+ // 也可以分法到客户端。 发送失败需要处理 或清理调
99
+ for (const client of this.#client) {
100
+ try {
101
+ client.ws.send(JSON.stringify(body.d));
102
+ }
103
+ catch (e) {
104
+ this.#error(e);
105
+ }
123
106
  }
124
107
  }
125
- catch (e) {
126
- console.error('parse error', e);
127
- }
128
- });
129
- // 处理关闭事件
130
- ws.on('close', () => {
131
- console.log(`Client ${clientId} disconnected`);
132
- this.#client = this.#client.filter(client => client.id !== clientId);
133
108
  });
134
- });
135
- const reconnect = () => {
136
- const ws = config.get('ws');
137
- if (!ws)
138
- return;
139
- // 使用了ws服务器
140
- this.#ws = new WebSocket(ws);
141
- this.#ws.on('open', () => {
142
- this.#count = 0;
143
- console.log('ws connected');
109
+ this.#app.use(router.routes());
110
+ this.#app.use(router.allowedMethods());
111
+ // 启动服务
112
+ const server = this.#app.listen(cfg.port, () => {
113
+ console.log('Server running at http://localhost:' + cfg.port + '/webhook');
144
114
  });
145
- this.#ws.on('message', data => {
146
- try {
115
+ // 创建 WebSocketServer 并监听同一个端口
116
+ const wss = new WebSocketServer({ server: server });
117
+ // 处理客户端连接
118
+ wss.on('connection', ws => {
119
+ const clientId = v4();
120
+ ws['clientId'] = clientId;
121
+ console.log(clientId, 'connection');
122
+ this.#client.push({ id: clientId, ws });
123
+ // 处理消息事件
124
+ ws.on('message', (message) => {
147
125
  // 拿到消息
148
- const body = JSON.parse(data.toString());
149
- for (const event of this.#events[body.t] || []) {
150
- event(body);
126
+ try {
127
+ const body = JSON.parse(message.toString());
128
+ for (const event of this.#events[body.t] || []) {
129
+ event(body);
130
+ }
151
131
  }
152
- }
153
- catch (e) {
154
- console.error('parse error', e);
155
- }
132
+ catch (e) {
133
+ this.#error(e);
134
+ }
135
+ });
136
+ // 处理关闭事件
137
+ ws.on('close', () => {
138
+ console.log(`Client ${clientId} disconnected`);
139
+ this.#client = this.#client.filter(client => client.id !== clientId);
140
+ });
156
141
  });
157
- this.#ws.on('close', () => {
158
- console.log('ws closed');
159
- // 重连5次,超过5次不再重连
160
- if (this.#count > 5) {
142
+ const reconnect = () => {
143
+ const ws = config.get('ws');
144
+ if (!ws)
161
145
  return;
162
- }
163
- // 23s 后重连
164
- setTimeout(() => {
165
- reconnect();
166
- }, 23000);
167
- });
168
- this.#ws.on('error', () => {
169
- console.log('ws error ');
170
- });
171
- };
172
- reconnect();
146
+ // 使用了ws服务器
147
+ this.#ws = new WebSocket(ws);
148
+ this.#ws.on('open', () => {
149
+ this.#count = 0;
150
+ console.log('ws connected');
151
+ });
152
+ this.#ws.on('message', data => {
153
+ try {
154
+ // 拿到消息
155
+ const body = JSON.parse(data.toString());
156
+ for (const event of this.#events[body.t] || []) {
157
+ event(body);
158
+ }
159
+ }
160
+ catch (e) {
161
+ this.#error(e);
162
+ }
163
+ });
164
+ this.#ws.on('close', () => {
165
+ console.log('ws closed');
166
+ // 重连5次,超过5次不再重连
167
+ if (this.#count > 5) {
168
+ return;
169
+ }
170
+ // 23s 后重连
171
+ setTimeout(() => {
172
+ reconnect();
173
+ }, 23000);
174
+ });
175
+ this.#ws.on('error', e => {
176
+ this.#error(e);
177
+ });
178
+ };
179
+ reconnect();
180
+ }
181
+ catch (e) {
182
+ this.#error(e);
183
+ }
184
+ }
185
+ /**
186
+ *
187
+ * @param error
188
+ */
189
+ #error(error) {
190
+ if (this.#events['ERROR']) {
191
+ for (const event of this.#events['ERROR'] || []) {
192
+ event(error);
193
+ }
194
+ }
173
195
  }
174
196
  }
175
197
 
package/lib/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import * as alemonjs from 'alemonjs';
2
+
3
+ declare const platform = "qq-bot";
4
+ declare const _default: () => alemonjs.ClientAPI;
5
+
6
+ export { _default as default, platform };
package/lib/index.js CHANGED
@@ -1,17 +1,15 @@
1
- import { defineBot, getConfig, useUserHashKey, OnProcessor } from 'alemonjs';
1
+ import { defineBot, getConfigValue, useUserHashKey, OnProcessor } from 'alemonjs';
2
2
  import { QQBotClient } from './client.js';
3
3
 
4
4
  const platform = 'qq-bot';
5
5
  var index = defineBot(() => {
6
- const cfg = getConfig();
7
- const config = cfg.value['qq-bot'];
8
- if (!config)
9
- return;
6
+ const value = getConfigValue();
7
+ const config = value['qq-bot'];
10
8
  const client = new QQBotClient({
11
- secret: config.secret,
12
- appId: config.appId,
13
- token: config.token,
14
- port: config.port,
9
+ secret: config?.secret,
10
+ app_id: config?.app_id,
11
+ token: config?.token,
12
+ port: config?.port,
15
13
  ws: config?.ws
16
14
  });
17
15
  // 连接
@@ -57,8 +55,7 @@ var index = defineBot(() => {
57
55
  MessageText: event.content?.trim(),
58
56
  OpenId: event.author.member_openid,
59
57
  CreateAt: Date.now(),
60
- //
61
- tag: 'GROUP_AT_MESSAGE_CREATE',
58
+ tag: 'group',
62
59
  value: null
63
60
  };
64
61
  // 当访问的时候获取
@@ -108,7 +105,7 @@ var index = defineBot(() => {
108
105
  CreateAt: Date.now(),
109
106
  OpenId: '',
110
107
  //
111
- tag: 'GROUP_AT_MESSAGE_CREATE',
108
+ tag: 'group',
112
109
  value: null
113
110
  };
114
111
  // 当访问的时候获取
@@ -165,7 +162,7 @@ var index = defineBot(() => {
165
162
  OpenId: event.guild_id,
166
163
  CreateAt: Date.now(),
167
164
  //
168
- tag: 'AT_MESSAGE_CREATE',
165
+ tag: 'guild',
169
166
  //
170
167
  value: null
171
168
  };
@@ -223,7 +220,7 @@ var index = defineBot(() => {
223
220
  OpenId: event.guild_id,
224
221
  CreateAt: Date.now(),
225
222
  //
226
- tag: 'AT_MESSAGE_CREATE',
223
+ tag: 'guild',
227
224
  //
228
225
  value: null
229
226
  };
@@ -307,7 +304,7 @@ var index = defineBot(() => {
307
304
  OpenId: event.guild_id,
308
305
  CreateAt: Date.now(),
309
306
  //
310
- tag: 'AT_MESSAGE_CREATE',
307
+ tag: 'guild',
311
308
  value: null
312
309
  };
313
310
  // 当访问的时候获取
@@ -319,6 +316,7 @@ var index = defineBot(() => {
319
316
  // 处理消息
320
317
  OnProcessor(e, 'message.create');
321
318
  });
319
+ client.on('ERROR', console.error);
322
320
  // FRIEND_ADD
323
321
  global.client = client;
324
322
  return {
@@ -327,66 +325,135 @@ var index = defineBot(() => {
327
325
  send: (event, val) => {
328
326
  if (val.length < 0)
329
327
  return Promise.all([]);
330
- const content = val
331
- .filter(item => item.type == 'Link' || item.type == 'Mention' || item.type == 'Text')
332
- .map(item => {
333
- if (item.type == 'Link') {
334
- return `[${item.options?.title ?? item.value}](${item.value})`;
335
- }
336
- else if (item.type == 'Mention') {
337
- if (item.value == 'everyone' ||
338
- item.value == 'all' ||
339
- item.value == '' ||
340
- typeof item.value != 'string') {
341
- return ``;
328
+ // 打 tag
329
+ const tag = event.tag;
330
+ if (tag == 'group') {
331
+ const content = val
332
+ .filter(item => item.type == 'Link' || item.type == 'Mention' || item.type == 'Text')
333
+ .map(item => {
334
+ if (item.type == 'Link') {
335
+ return `[${item.options?.title ?? item.value}](${item.value})`;
342
336
  }
343
- if (item.options?.belong == 'user') {
344
- return `<@${item.value}>`;
337
+ else if (item.type == 'Mention') {
338
+ if (item.value == 'everyone' ||
339
+ item.value == 'all' ||
340
+ item.value == '' ||
341
+ typeof item.value != 'string') {
342
+ return ``;
343
+ }
344
+ if (item.options?.belong == 'user') {
345
+ return `<@${item.value}>`;
346
+ }
347
+ return '';
348
+ // return `<qqbot-at-everyone />`
345
349
  }
346
- return '';
347
- // return `<qqbot-at-everyone />`
350
+ else if (item.type == 'Text') {
351
+ return item.value;
352
+ }
353
+ })
354
+ .join('');
355
+ if (content) {
356
+ return Promise.all([content].map(item => client.groupOpenMessages(event.GuildId, {
357
+ content: item,
358
+ msg_id: event.MessageId,
359
+ msg_type: 0,
360
+ msg_seq: client.getMessageSeq(event.MessageId)
361
+ })));
348
362
  }
349
- else if (item.type == 'Text') {
350
- return item.value;
363
+ const images = val.filter(item => item.type == 'Image').map(item => item.value);
364
+ if (images) {
365
+ return Promise.all(images.map(async (msg) => {
366
+ const file_info = await client
367
+ .postRichMediaByGroup(event.GuildId, {
368
+ file_type: 1,
369
+ file_data: msg.toString('base64')
370
+ })
371
+ .then(res => res?.file_info);
372
+ if (!file_info)
373
+ return Promise.resolve(null);
374
+ return client.groupOpenMessages(event.GuildId, {
375
+ content: '',
376
+ media: {
377
+ file_info
378
+ },
379
+ msg_id: event.MessageId,
380
+ msg_type: 7,
381
+ msg_seq: client.getMessageSeq(event.MessageId)
382
+ });
383
+ }));
351
384
  }
352
- })
353
- .join('');
354
- if (content) {
355
- return Promise.all([content].map(item => client.groupOpenMessages(event.GuildId, {
356
- content: item,
357
- msg_id: event.MessageId,
358
- msg_type: 0,
359
- msg_seq: client.getMessageSeq(event.MessageId)
360
- })));
361
385
  }
362
- const images = val.filter(item => item.type == 'Image').map(item => item.value);
363
- if (images) {
364
- return Promise.all(images.map(async (msg) => {
365
- const file_info = await client
366
- .postRichMediaByGroup(event.GuildId, {
367
- file_type: 1,
368
- file_data: msg.toString('base64')
369
- })
370
- .then(res => res?.file_info);
371
- if (!file_info)
372
- return Promise.resolve(null);
373
- return client.groupOpenMessages(event.GuildId, {
374
- content: '',
375
- media: {
376
- file_info
377
- },
386
+ else {
387
+ const content = val
388
+ .filter(item => item.type == 'Link' || item.type == 'Mention' || item.type == 'Text')
389
+ .map(item => {
390
+ if (item.type == 'Link') {
391
+ return `[${item.options?.title ?? item.value}](${item.value})`;
392
+ }
393
+ else if (item.type == 'Mention') {
394
+ if (item.value == 'everyone' ||
395
+ item.value == 'all' ||
396
+ item.value == '' ||
397
+ typeof item.value != 'string') {
398
+ return `@everyone`;
399
+ }
400
+ if (item.options?.belong == 'user') {
401
+ return `<@!${item.value}>`;
402
+ }
403
+ else if (item.options?.belong == 'channel') {
404
+ return `<#${item.value}>`;
405
+ }
406
+ return '';
407
+ }
408
+ else if (item.type == 'Text') {
409
+ return item.value;
410
+ }
411
+ })
412
+ .join('');
413
+ if (content) {
414
+ return Promise.all([content].map(item => client.channelsMessagesPost(event.ChannelId, {
415
+ content: item,
416
+ msg_id: event.MessageId
417
+ })));
418
+ }
419
+ const images = val.filter(item => item.type == 'Image').map(item => item.value);
420
+ if (images) {
421
+ return Promise.all(images.map(item => client.postImage(event.ChannelId, {
378
422
  msg_id: event.MessageId,
379
- msg_type: 7,
380
- msg_seq: client.getMessageSeq(event.MessageId)
381
- });
382
- }));
423
+ image: item
424
+ })));
425
+ }
383
426
  }
384
427
  return Promise.all([]);
385
428
  },
386
- mention: async () => {
429
+ mention: async (e) => {
430
+ const event = e.value;
431
+ const tag = e.tag;
387
432
  // const event = e.value
388
433
  const Metions = [];
389
- return Metions;
434
+ if (tag == 'group') {
435
+ return Metions;
436
+ }
437
+ if (event.mentions) {
438
+ const mentions = e.value['mentions'];
439
+ // 艾特消息处理
440
+ const MessageMention = mentions.map(item => {
441
+ return {
442
+ UserId: item.id,
443
+ IsMaster: false,
444
+ UserName: item.username,
445
+ IsBot: item.bot,
446
+ UserKey: useUserHashKey({
447
+ Platform: 'qq-guild-bot',
448
+ UserId: item.id
449
+ })
450
+ };
451
+ }) ?? [];
452
+ return MessageMention;
453
+ }
454
+ else {
455
+ return Metions;
456
+ }
390
457
  }
391
458
  }
392
459
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alemonjs/qq-bot",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "qq-bot",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",