onebots 0.0.15 → 0.0.16

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.
Files changed (46) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +84 -63
  3. package/lib/bin.d.ts +2 -2
  4. package/lib/bin.js +11 -5
  5. package/lib/config.sample.yaml +31 -0
  6. package/lib/db.d.ts +19 -19
  7. package/lib/db.js +91 -91
  8. package/lib/index.d.ts +5 -5
  9. package/lib/index.js +21 -21
  10. package/lib/onebot.d.ts +44 -44
  11. package/lib/onebot.js +133 -86
  12. package/lib/server/app.d.ts +52 -52
  13. package/lib/server/app.js +235 -232
  14. package/lib/server/router.d.ts +9 -9
  15. package/lib/server/router.js +32 -32
  16. package/lib/service/V11/action/common.d.ts +65 -65
  17. package/lib/service/V11/action/common.js +142 -142
  18. package/lib/service/V11/action/friend.d.ts +38 -38
  19. package/lib/service/V11/action/friend.js +44 -44
  20. package/lib/service/V11/action/group.d.ts +104 -104
  21. package/lib/service/V11/action/group.js +138 -138
  22. package/lib/service/V11/action/index.d.ts +9 -9
  23. package/lib/service/V11/action/index.js +10 -10
  24. package/lib/service/V11/config.d.ts +10 -10
  25. package/lib/service/V11/config.js +2 -2
  26. package/lib/service/V11/index.d.ts +95 -95
  27. package/lib/service/V11/index.js +499 -499
  28. package/lib/service/V12/action/common.d.ts +37 -33
  29. package/lib/service/V12/action/common.js +114 -108
  30. package/lib/service/V12/action/friend.d.ts +13 -13
  31. package/lib/service/V12/action/friend.js +15 -15
  32. package/lib/service/V12/action/group.d.ts +104 -104
  33. package/lib/service/V12/action/group.js +138 -138
  34. package/lib/service/V12/action/guild.d.ts +2 -2
  35. package/lib/service/V12/action/guild.js +6 -6
  36. package/lib/service/V12/action/index.d.ts +10 -10
  37. package/lib/service/V12/action/index.js +11 -11
  38. package/lib/service/V12/config.d.ts +17 -17
  39. package/lib/service/V12/config.js +2 -2
  40. package/lib/service/V12/index.d.ts +121 -102
  41. package/lib/service/V12/index.js +533 -538
  42. package/lib/types.d.ts +3 -3
  43. package/lib/types.js +2 -2
  44. package/lib/utils.d.ts +14 -14
  45. package/lib/utils.js +150 -150
  46. package/package.json +58 -58
@@ -1,499 +1,499 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.V11 = void 0;
7
- const oicq_1 = require("oicq");
8
- const action_1 = require("./action");
9
- const onebot_1 = require("../../onebot");
10
- const ws_1 = require("ws");
11
- const url_1 = require("url");
12
- const utils_1 = require("../../utils");
13
- const oicq2_cq_enable_1 = require("oicq2-cq-enable");
14
- const onebot_2 = require("../../onebot");
15
- const http_1 = __importDefault(require("http"));
16
- const https_1 = __importDefault(require("https"));
17
- const events_1 = require("events");
18
- const fs_1 = require("fs");
19
- class V11 extends events_1.EventEmitter {
20
- constructor(oneBot, client, config) {
21
- super();
22
- this.oneBot = oneBot;
23
- this.client = client;
24
- this.config = config;
25
- this.version = 'V11';
26
- this.timestamp = Date.now();
27
- this._queue = [];
28
- this.queue_running = false;
29
- this.wsr = new Set();
30
- this.action = new action_1.Action();
31
- this.logger = this.oneBot.app.getLogger(this.client.uin, this.version);
32
- }
33
- start(path) {
34
- this.path = `/${this.client.uin}`;
35
- if (path)
36
- this.path += path;
37
- if (this.config.use_http)
38
- this.startHttp();
39
- if (this.config.use_ws)
40
- this.startWs();
41
- this.config.http_reverse.forEach(config => {
42
- if (typeof config === 'string') {
43
- config = {
44
- url: config,
45
- access_token: this.config.access_token,
46
- secret: this.config.secret
47
- };
48
- }
49
- else {
50
- config = {
51
- access_token: this.config.access_token,
52
- secret: this.config.secret,
53
- ...config
54
- };
55
- }
56
- this.startHttpReverse(config);
57
- });
58
- this.config.ws_reverse.forEach(config => {
59
- this.startWsReverse(config);
60
- });
61
- if (this.config.heartbeat) {
62
- this.heartbeat = setInterval(() => {
63
- this.dispatch({
64
- self_id: this.client.uin,
65
- status: {
66
- online: this.client.status === oicq_1.OnlineStatus.Online,
67
- good: this.oneBot.status === onebot_1.OneBotStatus.Good
68
- },
69
- time: Math.floor(Date.now() / 1000),
70
- post_type: "meta_event",
71
- meta_event_type: "heartbeat",
72
- interval: this.config.heartbeat * 1000,
73
- });
74
- }, this.config.heartbeat * 1000);
75
- }
76
- }
77
- startHttp() {
78
- this.oneBot.app.router.all(new RegExp(`^${this.path}/(.*)$`), this._httpRequestHandler.bind(this));
79
- this.logger.mark(`开启http服务器成功,监听:http://127.0.0.1:${this.oneBot.app.config.port}${this.path}`);
80
- }
81
- startHttpReverse(config) {
82
- this.on('dispatch', (unserialized) => {
83
- const serialized = JSON.stringify(unserialized);
84
- const options = {
85
- method: "POST",
86
- timeout: this.config.post_timeout * 1000,
87
- headers: {
88
- "Content-Type": "application/json",
89
- "Content-Length": Buffer.byteLength(serialized),
90
- "X-Self-ID": String(this.client.uin),
91
- "User-Agent": "OneBot",
92
- },
93
- };
94
- if (this.config.secret) {
95
- //@ts-ignore
96
- options.headers["X-Signature"] = "sha1=" + crypto.createHmac("sha1", String(this.config.secret)).update(serialized).digest("hex");
97
- }
98
- const protocol = config.url.startsWith("https") ? https_1.default : http_1.default;
99
- try {
100
- protocol.request(config.url, options, (res) => {
101
- if (res.statusCode !== 200)
102
- return this.logger.warn(`POST(${config.url})上报事件收到非200响应:` + res.statusCode);
103
- let data = "";
104
- res.setEncoding("utf-8");
105
- res.on("data", (chunk) => data += chunk);
106
- res.on("end", () => {
107
- this.logger.debug(`收到HTTP响应 ${res.statusCode} :` + data);
108
- if (!data)
109
- return;
110
- try {
111
- this._quickOperate(unserialized, JSON.parse(data));
112
- }
113
- catch (e) {
114
- this.logger.error(`快速操作遇到错误:` + e.message);
115
- }
116
- });
117
- }).on("error", (err) => {
118
- this.logger.error(`POST(${config.url})上报事件失败:` + err.message);
119
- }).end(serialized, () => {
120
- this.logger.debug(`POST(${config.url})上报事件成功: ` + serialized);
121
- });
122
- }
123
- catch (e) {
124
- this.logger.error(`POST(${config.url})上报失败:` + e.message);
125
- }
126
- });
127
- }
128
- startWs() {
129
- this.wss = this.oneBot.app.router.ws(this.path, this.oneBot.app.httpServer);
130
- this.logger.mark(`开启ws服务器成功,监听:ws://127.0.0.1:${this.oneBot.app.config.port}${this.path}`);
131
- this.wss.on("error", (err) => {
132
- this.logger.error(err.message);
133
- });
134
- this.wss.on("connection", (ws, req) => {
135
- this.logger.info(`ws客户端(${req.url})已连接`);
136
- ws.on("error", (err) => {
137
- this.logger.error(`ws客户端(${req.url})报错:${err.message}`);
138
- });
139
- ws.on("close", (code, reason) => {
140
- this.logger.warn(`ws客户端(${req.url})连接关闭,关闭码${code},关闭理由:` + reason);
141
- });
142
- if (this.config.access_token) {
143
- const url = new url_1.URL(req.url, "http://127.0.0.1");
144
- const token = url.searchParams.get('access_token');
145
- if (token)
146
- req.headers["authorization"] = `Bearer ${token}`;
147
- if (!req.headers["authorization"] || req.headers["authorization"] !== `Bearer ${this.config.access_token}`)
148
- return ws.close(1002, "wrong access token");
149
- }
150
- this._webSocketHandler(ws);
151
- });
152
- this.on('dispatch', (serialized) => {
153
- for (const ws of this.wss.clients) {
154
- ws.send(serialized, (err) => {
155
- if (err)
156
- this.logger.error(`正向WS(${ws.url})上报事件失败: ` + err.message);
157
- else
158
- this.logger.debug(`正向WS(${ws.url})上报事件成功: ` + serialized);
159
- });
160
- }
161
- });
162
- }
163
- startWsReverse(url) {
164
- const ws = this._createWsr(url);
165
- this.on('dispatch', (serialized) => {
166
- if (this.wsr.has(ws)) {
167
- ws.send(serialized, (err) => {
168
- if (err)
169
- this.logger.error(`反向WS(${ws.url})上报事件失败: ` + err.message);
170
- else
171
- this.logger.debug(`反向WS(${ws.url})上报事件成功: ` + serialized);
172
- });
173
- }
174
- });
175
- }
176
- async stop(force) {
177
- if (this.client.status === oicq_1.OnlineStatus.Online) {
178
- await this.client.terminate();
179
- }
180
- if (force) {
181
- (0, fs_1.rmSync)(this.client.dir, { force: true, recursive: true });
182
- }
183
- }
184
- dispatch(data) {
185
- if (!data.post_type)
186
- data.post_type = 'system';
187
- if (data.post_type === 'system') {
188
- }
189
- if (data.message && data.post_type === 'message') {
190
- data.message = this.config.post_message_format === 'array' ? (0, oicq2_cq_enable_1.toSegment)(data.message) : (0, oicq2_cq_enable_1.toCqcode)(data);
191
- }
192
- data.time = Math.floor(Date.now() / 1000);
193
- this.emit('dispatch', JSON.stringify(data));
194
- }
195
- async _httpRequestHandler(ctx) {
196
- if (ctx.method === 'OPTIONS') {
197
- return ctx.writeHead(200, {
198
- 'Access-Control-Allow-Origin': '*',
199
- 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
200
- 'Access-Control-Allow-Headers': 'Content-Type, authorization'
201
- }).end();
202
- }
203
- const url = new url_1.URL(ctx.url, `http://127.0.0.1`);
204
- if (this.config.access_token) {
205
- if (ctx.headers["authorization"]) {
206
- if (ctx.headers["authorization"] !== `Bearer ${this.config.access_token}`)
207
- return ctx.res.writeHead(403).end();
208
- }
209
- else {
210
- const access_token = url.searchParams.get("access_token");
211
- if (!access_token)
212
- return ctx.res.writeHead(401).end();
213
- else if (access_token !== this.config.access_token)
214
- return ctx.res.writeHead(403).end();
215
- }
216
- }
217
- ctx.res.setHeader("Content-Type", "application/json; charset=utf-8");
218
- if (this.config.enable_cors)
219
- ctx.res.setHeader("Access-Control-Allow-Origin", "*");
220
- const action = url.pathname.replace(`${this.path}`, '').slice(1);
221
- if (ctx.method === "GET") {
222
- try {
223
- const ret = await this.apply({ action, params: ctx.query });
224
- ctx.res.writeHead(200).end(ret);
225
- }
226
- catch (e) {
227
- ctx.res.writeHead(500).end(e.message);
228
- }
229
- }
230
- else if (ctx.method === "POST") {
231
- try {
232
- const params = { ...(ctx.request.query || {}), ...(ctx.request.body || {}) };
233
- const ret = await this.apply({ action, params });
234
- ctx.res.writeHead(200).end(ret);
235
- }
236
- catch (e) {
237
- ctx.res.writeHead(500).end(e.message);
238
- }
239
- }
240
- else {
241
- ctx.res.writeHead(405).end();
242
- }
243
- }
244
- /**
245
- * 处理ws消息
246
- */
247
- _webSocketHandler(ws) {
248
- ws.on("message", async (msg) => {
249
- this.logger.info(" 收到ws消息:" + msg);
250
- var data;
251
- try {
252
- data = JSON.parse(String(msg));
253
- let ret;
254
- if (data.action.startsWith(".handle_quick_operation")) {
255
- const event = data.params.context, res = data.params.operation;
256
- this._quickOperate(event, res);
257
- ret = JSON.stringify({
258
- retcode: 0,
259
- status: "async",
260
- data: null,
261
- error: null,
262
- echo: data.echo
263
- });
264
- }
265
- else {
266
- ret = await this.apply(data);
267
- }
268
- ws.send(ret);
269
- }
270
- catch (e) {
271
- let code, message;
272
- if (e instanceof onebot_2.NotFoundError) {
273
- code = 1404;
274
- message = "不支持的api";
275
- }
276
- else {
277
- code = 1400;
278
- message = "请求格式错误";
279
- }
280
- ws.send(JSON.stringify({
281
- retcode: code,
282
- status: "failed",
283
- data: null,
284
- error: {
285
- code, message
286
- },
287
- echo: data?.echo
288
- }));
289
- }
290
- });
291
- ws.send(JSON.stringify(V11.genMetaEvent(this.client.uin, "connect")));
292
- ws.send(JSON.stringify(V11.genMetaEvent(this.client.uin, "enable")));
293
- }
294
- /**
295
- * 创建反向ws
296
- */
297
- _createWsr(url) {
298
- const timestmap = Date.now();
299
- const headers = {
300
- "X-Self-ID": String(this.client.uin),
301
- "X-Client-Role": "Universal",
302
- "User-Agent": "OneBot",
303
- };
304
- if (this.config.access_token)
305
- headers.Authorization = "Bearer " + this.config.access_token;
306
- const ws = new ws_1.WebSocket(url, { headers });
307
- ws.on("error", (err) => {
308
- this.logger.error(err.message);
309
- });
310
- ws.on("open", () => {
311
- this.logger.info(`反向ws(${url})连接成功。`);
312
- this.wsr.add(ws);
313
- this._webSocketHandler(ws);
314
- });
315
- ws.on("close", (code) => {
316
- this.wsr.delete(ws);
317
- if (timestmap < this.timestamp)
318
- return;
319
- this.logger.warn(`反向ws(${url})被关闭,关闭码${code},将在${this.config.reconnect_interval}秒后尝试重连。`);
320
- setTimeout(() => {
321
- if (timestmap < this.timestamp)
322
- return;
323
- this._createWsr(url);
324
- }, this.config.reconnect_interval * 1000);
325
- });
326
- return ws;
327
- }
328
- /**
329
- * 快速操作
330
- */
331
- _quickOperate(event, res) {
332
- if (event.post_type === "message") {
333
- if (res.reply) {
334
- if (event.message_type === "discuss")
335
- return;
336
- const action = event.message_type === "private" ? "sendPrivateMsg" : "sendGroupMsg";
337
- const id = event.message_type === "private" ? event.user_id : event.group_id;
338
- this.client[action](id, res.reply, res.auto_escape);
339
- }
340
- if (event.message_type === "group") {
341
- if (res.delete)
342
- this.client.deleteMsg(event.message_id);
343
- if (res.kick && !event.anonymous)
344
- this.client.setGroupKick(event.group_id, event.user_id, res.reject_add_request);
345
- if (res.ban)
346
- this.client.setGroupBan(event.group_id, event.user_id, res.ban_duration > 0 ? res.ban_duration : 1800);
347
- }
348
- }
349
- if (event.post_type === "request" && "approve" in res) {
350
- const action = event.request_type === "friend" ? "setFriendAddRequest" : "setGroupAddRequest";
351
- this.client[action](event.flag, res.approve, res.reason ? res.reason : "", !!res.block);
352
- }
353
- }
354
- /**
355
- * 调用api
356
- */
357
- async apply(req) {
358
- let { action, params, echo } = req;
359
- action = (0, utils_1.toLine)(action);
360
- let is_async = action.includes("_async");
361
- if (is_async)
362
- action = action.replace("_async", "");
363
- let is_queue = action.includes("_rate_limited");
364
- if (is_queue)
365
- action = action.replace("_rate_limited", "");
366
- if (action === 'send_msg') {
367
- if (["private", "group", "discuss"].includes(params.message_type)) {
368
- action = "send_" + params.message_type + "_msg";
369
- }
370
- else if (params.user_id)
371
- action = "send_private_msg";
372
- else if (params.group_id)
373
- action = "send_group_msg";
374
- else if (params.discuss_id)
375
- action = "send_discuss_msg";
376
- else
377
- throw new Error('required message_type or input (user_id/group_id)');
378
- }
379
- const method = (0, utils_1.toHump)(action);
380
- if (Reflect.has(this.action, method)) {
381
- const ARGS = String(Reflect.get(this.action, method)).match(/\(.*\)/)?.[0]
382
- .replace("(", "")
383
- .replace(")", "")
384
- .split(",")
385
- .filter(Boolean).map(v => v.replace(/=.+/, "").trim());
386
- const args = [];
387
- for (let k of ARGS) {
388
- if (Reflect.has(params, k)) {
389
- if (onebot_2.BOOLS.includes(k))
390
- params[k] = (0, utils_1.toBool)(params[k]);
391
- if (k === 'message') {
392
- if (typeof params[k] === 'string') {
393
- params[k] = (0, oicq2_cq_enable_1.fromCqcode)(params[k]);
394
- }
395
- else {
396
- params[k] = (0, oicq2_cq_enable_1.fromSegment)(params[k]);
397
- }
398
- }
399
- args.push(params[k]);
400
- }
401
- }
402
- let ret, result;
403
- if (is_queue) {
404
- this._queue.push({ method, args });
405
- this._runQueue();
406
- result = V11.ok(null, 0, true);
407
- }
408
- else {
409
- try {
410
- ret = this.action[method].apply(this, args);
411
- }
412
- catch (e) {
413
- return JSON.stringify(V11.error(e.message));
414
- }
415
- if (ret instanceof Promise) {
416
- if (is_async) {
417
- result = V11.ok(null, 0, true);
418
- }
419
- else {
420
- result = V11.ok(await ret, 0, false);
421
- }
422
- }
423
- else {
424
- result = V11.ok(await ret, 0, false);
425
- }
426
- }
427
- if (result.data instanceof Map)
428
- result.data = [...result.data.values()];
429
- if (echo) {
430
- result.echo = echo;
431
- }
432
- return JSON.stringify(result);
433
- }
434
- else
435
- throw new onebot_2.NotFoundError();
436
- }
437
- /**
438
- * 限速队列调用
439
- */
440
- async _runQueue() {
441
- if (this.queue_running)
442
- return;
443
- while (this._queue.length > 0) {
444
- this.queue_running = true;
445
- const task = this._queue.shift();
446
- const { method, args } = task;
447
- this.action[method].apply(this, args);
448
- await new Promise((resolve) => {
449
- setTimeout(resolve, this.config.rate_limit_interval * 1000);
450
- });
451
- this.queue_running = false;
452
- }
453
- }
454
- }
455
- exports.V11 = V11;
456
- (function (V11) {
457
- function ok(data, retcode = 0, pending) {
458
- return {
459
- retcode,
460
- status: pending ? 'async' : 'ok',
461
- data,
462
- error: null
463
- };
464
- }
465
- V11.ok = ok;
466
- function error(error, retcode = 1) {
467
- return {
468
- retcode,
469
- status: 'error',
470
- data: null,
471
- error
472
- };
473
- }
474
- V11.error = error;
475
- V11.defaultConfig = {
476
- heartbeat: 3,
477
- access_token: '',
478
- post_timeout: 15,
479
- secret: '',
480
- rate_limit_interval: 4,
481
- post_message_format: 'string',
482
- reconnect_interval: 3,
483
- use_http: true,
484
- enable_cors: true,
485
- use_ws: true,
486
- http_reverse: [],
487
- ws_reverse: []
488
- };
489
- function genMetaEvent(uin, type) {
490
- return {
491
- self_id: uin,
492
- time: Math.floor(Date.now() / 1000),
493
- post_type: "meta_event",
494
- meta_event_type: "lifecycle",
495
- sub_type: type,
496
- };
497
- }
498
- V11.genMetaEvent = genMetaEvent;
499
- })(V11 = exports.V11 || (exports.V11 = {}));
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.V11 = void 0;
7
+ const oicq_1 = require("oicq");
8
+ const action_1 = require("./action");
9
+ const onebot_1 = require("../../onebot");
10
+ const ws_1 = require("ws");
11
+ const url_1 = require("url");
12
+ const utils_1 = require("../../utils");
13
+ const oicq2_cq_enable_1 = require("oicq2-cq-enable");
14
+ const onebot_2 = require("../../onebot");
15
+ const http_1 = __importDefault(require("http"));
16
+ const https_1 = __importDefault(require("https"));
17
+ const events_1 = require("events");
18
+ const fs_1 = require("fs");
19
+ class V11 extends events_1.EventEmitter {
20
+ constructor(oneBot, client, config) {
21
+ super();
22
+ this.oneBot = oneBot;
23
+ this.client = client;
24
+ this.config = config;
25
+ this.version = 'V11';
26
+ this.timestamp = Date.now();
27
+ this._queue = [];
28
+ this.queue_running = false;
29
+ this.wsr = new Set();
30
+ this.action = new action_1.Action();
31
+ this.logger = this.oneBot.app.getLogger(this.client.uin, this.version);
32
+ }
33
+ start(path) {
34
+ this.path = `/${this.client.uin}`;
35
+ if (path)
36
+ this.path += path;
37
+ if (this.config.use_http)
38
+ this.startHttp();
39
+ if (this.config.use_ws)
40
+ this.startWs();
41
+ this.config.http_reverse.forEach(config => {
42
+ if (typeof config === 'string') {
43
+ config = {
44
+ url: config,
45
+ access_token: this.config.access_token,
46
+ secret: this.config.secret
47
+ };
48
+ }
49
+ else {
50
+ config = {
51
+ access_token: this.config.access_token,
52
+ secret: this.config.secret,
53
+ ...config
54
+ };
55
+ }
56
+ this.startHttpReverse(config);
57
+ });
58
+ this.config.ws_reverse.forEach(config => {
59
+ this.startWsReverse(config);
60
+ });
61
+ if (this.config.heartbeat) {
62
+ this.heartbeat = setInterval(() => {
63
+ this.dispatch({
64
+ self_id: this.client.uin,
65
+ status: {
66
+ online: this.client.status === oicq_1.OnlineStatus.Online,
67
+ good: this.oneBot.status === onebot_1.OneBotStatus.Good
68
+ },
69
+ time: Math.floor(Date.now() / 1000),
70
+ post_type: "meta_event",
71
+ meta_event_type: "heartbeat",
72
+ interval: this.config.heartbeat * 1000,
73
+ });
74
+ }, this.config.heartbeat * 1000);
75
+ }
76
+ }
77
+ startHttp() {
78
+ this.oneBot.app.router.all(new RegExp(`^${this.path}/(.*)$`), this._httpRequestHandler.bind(this));
79
+ this.logger.mark(`开启http服务器成功,监听:http://127.0.0.1:${this.oneBot.app.config.port}${this.path}`);
80
+ }
81
+ startHttpReverse(config) {
82
+ this.on('dispatch', (unserialized) => {
83
+ const serialized = JSON.stringify(unserialized);
84
+ const options = {
85
+ method: "POST",
86
+ timeout: this.config.post_timeout * 1000,
87
+ headers: {
88
+ "Content-Type": "application/json",
89
+ "Content-Length": Buffer.byteLength(serialized),
90
+ "X-Self-ID": String(this.client.uin),
91
+ "User-Agent": "OneBot",
92
+ },
93
+ };
94
+ if (this.config.secret) {
95
+ //@ts-ignore
96
+ options.headers["X-Signature"] = "sha1=" + crypto.createHmac("sha1", String(this.config.secret)).update(serialized).digest("hex");
97
+ }
98
+ const protocol = config.url.startsWith("https") ? https_1.default : http_1.default;
99
+ try {
100
+ protocol.request(config.url, options, (res) => {
101
+ if (res.statusCode !== 200)
102
+ return this.logger.warn(`POST(${config.url})上报事件收到非200响应:` + res.statusCode);
103
+ let data = "";
104
+ res.setEncoding("utf-8");
105
+ res.on("data", (chunk) => data += chunk);
106
+ res.on("end", () => {
107
+ this.logger.debug(`收到HTTP响应 ${res.statusCode} :` + data);
108
+ if (!data)
109
+ return;
110
+ try {
111
+ this._quickOperate(unserialized, JSON.parse(data));
112
+ }
113
+ catch (e) {
114
+ this.logger.error(`快速操作遇到错误:` + e.message);
115
+ }
116
+ });
117
+ }).on("error", (err) => {
118
+ this.logger.error(`POST(${config.url})上报事件失败:` + err.message);
119
+ }).end(serialized, () => {
120
+ this.logger.debug(`POST(${config.url})上报事件成功: ` + serialized);
121
+ });
122
+ }
123
+ catch (e) {
124
+ this.logger.error(`POST(${config.url})上报失败:` + e.message);
125
+ }
126
+ });
127
+ }
128
+ startWs() {
129
+ this.wss = this.oneBot.app.router.ws(this.path, this.oneBot.app.httpServer);
130
+ this.logger.mark(`开启ws服务器成功,监听:ws://127.0.0.1:${this.oneBot.app.config.port}${this.path}`);
131
+ this.wss.on("error", (err) => {
132
+ this.logger.error(err.message);
133
+ });
134
+ this.wss.on("connection", (ws, req) => {
135
+ this.logger.info(`ws客户端(${req.url})已连接`);
136
+ ws.on("error", (err) => {
137
+ this.logger.error(`ws客户端(${req.url})报错:${err.message}`);
138
+ });
139
+ ws.on("close", (code, reason) => {
140
+ this.logger.warn(`ws客户端(${req.url})连接关闭,关闭码${code},关闭理由:` + reason);
141
+ });
142
+ if (this.config.access_token) {
143
+ const url = new url_1.URL(req.url, "http://127.0.0.1");
144
+ const token = url.searchParams.get('access_token');
145
+ if (token)
146
+ req.headers["authorization"] = `Bearer ${token}`;
147
+ if (!req.headers["authorization"] || req.headers["authorization"] !== `Bearer ${this.config.access_token}`)
148
+ return ws.close(1002, "wrong access token");
149
+ }
150
+ this._webSocketHandler(ws);
151
+ });
152
+ this.on('dispatch', (serialized) => {
153
+ for (const ws of this.wss.clients) {
154
+ ws.send(serialized, (err) => {
155
+ if (err)
156
+ this.logger.error(`正向WS(${ws.url})上报事件失败: ` + err.message);
157
+ else
158
+ this.logger.debug(`正向WS(${ws.url})上报事件成功: ` + serialized);
159
+ });
160
+ }
161
+ });
162
+ }
163
+ startWsReverse(url) {
164
+ const ws = this._createWsr(url);
165
+ this.on('dispatch', (serialized) => {
166
+ if (this.wsr.has(ws)) {
167
+ ws.send(serialized, (err) => {
168
+ if (err)
169
+ this.logger.error(`反向WS(${ws.url})上报事件失败: ` + err.message);
170
+ else
171
+ this.logger.debug(`反向WS(${ws.url})上报事件成功: ` + serialized);
172
+ });
173
+ }
174
+ });
175
+ }
176
+ async stop(force) {
177
+ if (this.client.status === oicq_1.OnlineStatus.Online) {
178
+ await this.client.terminate();
179
+ }
180
+ if (force) {
181
+ (0, fs_1.rmSync)(this.client.dir, { force: true, recursive: true });
182
+ }
183
+ }
184
+ dispatch(data) {
185
+ if (!data.post_type)
186
+ data.post_type = 'system';
187
+ if (data.post_type === 'system') {
188
+ }
189
+ if (data.message && data.post_type === 'message') {
190
+ data.message = this.config.post_message_format === 'array' ? (0, oicq2_cq_enable_1.toSegment)(data.message) : (0, oicq2_cq_enable_1.toCqcode)(data);
191
+ }
192
+ data.time = Math.floor(Date.now() / 1000);
193
+ this.emit('dispatch', JSON.stringify(data));
194
+ }
195
+ async _httpRequestHandler(ctx) {
196
+ if (ctx.method === 'OPTIONS') {
197
+ return ctx.writeHead(200, {
198
+ 'Access-Control-Allow-Origin': '*',
199
+ 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
200
+ 'Access-Control-Allow-Headers': 'Content-Type, authorization'
201
+ }).end();
202
+ }
203
+ const url = new url_1.URL(ctx.url, `http://127.0.0.1`);
204
+ if (this.config.access_token) {
205
+ if (ctx.headers["authorization"]) {
206
+ if (ctx.headers["authorization"] !== `Bearer ${this.config.access_token}`)
207
+ return ctx.res.writeHead(403).end();
208
+ }
209
+ else {
210
+ const access_token = url.searchParams.get("access_token");
211
+ if (!access_token)
212
+ return ctx.res.writeHead(401).end();
213
+ else if (access_token !== this.config.access_token)
214
+ return ctx.res.writeHead(403).end();
215
+ }
216
+ }
217
+ ctx.res.setHeader("Content-Type", "application/json; charset=utf-8");
218
+ if (this.config.enable_cors)
219
+ ctx.res.setHeader("Access-Control-Allow-Origin", "*");
220
+ const action = url.pathname.replace(`${this.path}`, '').slice(1);
221
+ if (ctx.method === "GET") {
222
+ try {
223
+ const ret = await this.apply({ action, params: ctx.query });
224
+ ctx.res.writeHead(200).end(ret);
225
+ }
226
+ catch (e) {
227
+ ctx.res.writeHead(500).end(e.message);
228
+ }
229
+ }
230
+ else if (ctx.method === "POST") {
231
+ try {
232
+ const params = { ...(ctx.request.query || {}), ...(ctx.request.body || {}) };
233
+ const ret = await this.apply({ action, params });
234
+ ctx.res.writeHead(200).end(ret);
235
+ }
236
+ catch (e) {
237
+ ctx.res.writeHead(500).end(e.message);
238
+ }
239
+ }
240
+ else {
241
+ ctx.res.writeHead(405).end();
242
+ }
243
+ }
244
+ /**
245
+ * 处理ws消息
246
+ */
247
+ _webSocketHandler(ws) {
248
+ ws.on("message", async (msg) => {
249
+ this.logger.info(" 收到ws消息:" + msg);
250
+ var data;
251
+ try {
252
+ data = JSON.parse(String(msg));
253
+ let ret;
254
+ if (data.action.startsWith(".handle_quick_operation")) {
255
+ const event = data.params.context, res = data.params.operation;
256
+ this._quickOperate(event, res);
257
+ ret = JSON.stringify({
258
+ retcode: 0,
259
+ status: "async",
260
+ data: null,
261
+ error: null,
262
+ echo: data.echo
263
+ });
264
+ }
265
+ else {
266
+ ret = await this.apply(data);
267
+ }
268
+ ws.send(ret);
269
+ }
270
+ catch (e) {
271
+ let code, message;
272
+ if (e instanceof onebot_2.NotFoundError) {
273
+ code = 1404;
274
+ message = "不支持的api";
275
+ }
276
+ else {
277
+ code = 1400;
278
+ message = "请求格式错误";
279
+ }
280
+ ws.send(JSON.stringify({
281
+ retcode: code,
282
+ status: "failed",
283
+ data: null,
284
+ error: {
285
+ code, message
286
+ },
287
+ echo: data?.echo
288
+ }));
289
+ }
290
+ });
291
+ ws.send(JSON.stringify(V11.genMetaEvent(this.client.uin, "connect")));
292
+ ws.send(JSON.stringify(V11.genMetaEvent(this.client.uin, "enable")));
293
+ }
294
+ /**
295
+ * 创建反向ws
296
+ */
297
+ _createWsr(url) {
298
+ const timestmap = Date.now();
299
+ const headers = {
300
+ "X-Self-ID": String(this.client.uin),
301
+ "X-Client-Role": "Universal",
302
+ "User-Agent": "OneBot",
303
+ };
304
+ if (this.config.access_token)
305
+ headers.Authorization = "Bearer " + this.config.access_token;
306
+ const ws = new ws_1.WebSocket(url, { headers });
307
+ ws.on("error", (err) => {
308
+ this.logger.error(err.message);
309
+ });
310
+ ws.on("open", () => {
311
+ this.logger.info(`反向ws(${url})连接成功。`);
312
+ this.wsr.add(ws);
313
+ this._webSocketHandler(ws);
314
+ });
315
+ ws.on("close", (code) => {
316
+ this.wsr.delete(ws);
317
+ if (timestmap < this.timestamp)
318
+ return;
319
+ this.logger.warn(`反向ws(${url})被关闭,关闭码${code},将在${this.config.reconnect_interval}秒后尝试重连。`);
320
+ setTimeout(() => {
321
+ if (timestmap < this.timestamp)
322
+ return;
323
+ this._createWsr(url);
324
+ }, this.config.reconnect_interval * 1000);
325
+ });
326
+ return ws;
327
+ }
328
+ /**
329
+ * 快速操作
330
+ */
331
+ _quickOperate(event, res) {
332
+ if (event.post_type === "message") {
333
+ if (res.reply) {
334
+ if (event.message_type === "discuss")
335
+ return;
336
+ const action = event.message_type === "private" ? "sendPrivateMsg" : "sendGroupMsg";
337
+ const id = event.message_type === "private" ? event.user_id : event.group_id;
338
+ this.client[action](id, res.reply, res.auto_escape);
339
+ }
340
+ if (event.message_type === "group") {
341
+ if (res.delete)
342
+ this.client.deleteMsg(event.message_id);
343
+ if (res.kick && !event.anonymous)
344
+ this.client.setGroupKick(event.group_id, event.user_id, res.reject_add_request);
345
+ if (res.ban)
346
+ this.client.setGroupBan(event.group_id, event.user_id, res.ban_duration > 0 ? res.ban_duration : 1800);
347
+ }
348
+ }
349
+ if (event.post_type === "request" && "approve" in res) {
350
+ const action = event.request_type === "friend" ? "setFriendAddRequest" : "setGroupAddRequest";
351
+ this.client[action](event.flag, res.approve, res.reason ? res.reason : "", !!res.block);
352
+ }
353
+ }
354
+ /**
355
+ * 调用api
356
+ */
357
+ async apply(req) {
358
+ let { action, params, echo } = req;
359
+ action = (0, utils_1.toLine)(action);
360
+ let is_async = action.includes("_async");
361
+ if (is_async)
362
+ action = action.replace("_async", "");
363
+ let is_queue = action.includes("_rate_limited");
364
+ if (is_queue)
365
+ action = action.replace("_rate_limited", "");
366
+ if (action === 'send_msg') {
367
+ if (["private", "group", "discuss"].includes(params.message_type)) {
368
+ action = "send_" + params.message_type + "_msg";
369
+ }
370
+ else if (params.user_id)
371
+ action = "send_private_msg";
372
+ else if (params.group_id)
373
+ action = "send_group_msg";
374
+ else if (params.discuss_id)
375
+ action = "send_discuss_msg";
376
+ else
377
+ throw new Error('required message_type or input (user_id/group_id)');
378
+ }
379
+ const method = (0, utils_1.toHump)(action);
380
+ if (Reflect.has(this.action, method)) {
381
+ const ARGS = String(Reflect.get(this.action, method)).match(/\(.*\)/)?.[0]
382
+ .replace("(", "")
383
+ .replace(")", "")
384
+ .split(",")
385
+ .filter(Boolean).map(v => v.replace(/=.+/, "").trim());
386
+ const args = [];
387
+ for (let k of ARGS) {
388
+ if (Reflect.has(params, k)) {
389
+ if (onebot_2.BOOLS.includes(k))
390
+ params[k] = (0, utils_1.toBool)(params[k]);
391
+ if (k === 'message') {
392
+ if (typeof params[k] === 'string') {
393
+ params[k] = (0, oicq2_cq_enable_1.fromCqcode)(params[k]);
394
+ }
395
+ else {
396
+ params[k] = (0, oicq2_cq_enable_1.fromSegment)(params[k]);
397
+ }
398
+ }
399
+ args.push(params[k]);
400
+ }
401
+ }
402
+ let ret, result;
403
+ if (is_queue) {
404
+ this._queue.push({ method, args });
405
+ this._runQueue();
406
+ result = V11.ok(null, 0, true);
407
+ }
408
+ else {
409
+ try {
410
+ ret = this.action[method].apply(this, args);
411
+ }
412
+ catch (e) {
413
+ return JSON.stringify(V11.error(e.message));
414
+ }
415
+ if (ret instanceof Promise) {
416
+ if (is_async) {
417
+ result = V11.ok(null, 0, true);
418
+ }
419
+ else {
420
+ result = V11.ok(await ret, 0, false);
421
+ }
422
+ }
423
+ else {
424
+ result = V11.ok(await ret, 0, false);
425
+ }
426
+ }
427
+ if (result.data instanceof Map)
428
+ result.data = [...result.data.values()];
429
+ if (echo) {
430
+ result.echo = echo;
431
+ }
432
+ return JSON.stringify(result);
433
+ }
434
+ else
435
+ throw new onebot_2.NotFoundError();
436
+ }
437
+ /**
438
+ * 限速队列调用
439
+ */
440
+ async _runQueue() {
441
+ if (this.queue_running)
442
+ return;
443
+ while (this._queue.length > 0) {
444
+ this.queue_running = true;
445
+ const task = this._queue.shift();
446
+ const { method, args } = task;
447
+ this.action[method].apply(this, args);
448
+ await new Promise((resolve) => {
449
+ setTimeout(resolve, this.config.rate_limit_interval * 1000);
450
+ });
451
+ this.queue_running = false;
452
+ }
453
+ }
454
+ }
455
+ exports.V11 = V11;
456
+ (function (V11) {
457
+ function ok(data, retcode = 0, pending) {
458
+ return {
459
+ retcode,
460
+ status: pending ? 'async' : 'ok',
461
+ data,
462
+ error: null
463
+ };
464
+ }
465
+ V11.ok = ok;
466
+ function error(error, retcode = 1) {
467
+ return {
468
+ retcode,
469
+ status: 'error',
470
+ data: null,
471
+ error
472
+ };
473
+ }
474
+ V11.error = error;
475
+ V11.defaultConfig = {
476
+ heartbeat: 3,
477
+ access_token: '',
478
+ post_timeout: 15,
479
+ secret: '',
480
+ rate_limit_interval: 4,
481
+ post_message_format: 'string',
482
+ reconnect_interval: 3,
483
+ use_http: true,
484
+ enable_cors: true,
485
+ use_ws: true,
486
+ http_reverse: [],
487
+ ws_reverse: []
488
+ };
489
+ function genMetaEvent(uin, type) {
490
+ return {
491
+ self_id: uin,
492
+ time: Math.floor(Date.now() / 1000),
493
+ post_type: "meta_event",
494
+ meta_event_type: "lifecycle",
495
+ sub_type: type,
496
+ };
497
+ }
498
+ V11.genMetaEvent = genMetaEvent;
499
+ })(V11 = exports.V11 || (exports.V11 = {}));