oicq-icalingua-plus-plus 1.22.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.
Files changed (50) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +73 -0
  3. package/bin/oicq +2 -0
  4. package/http-api/README.md +187 -0
  5. package/http-api/api.js +217 -0
  6. package/http-api/config.sample.js +44 -0
  7. package/http-api/core.js +480 -0
  8. package/http-api/cq-notice.js +39 -0
  9. package/http-api/filter.js +128 -0
  10. package/http-api/index.js +39 -0
  11. package/index.d.ts +1214 -0
  12. package/index.js +34 -0
  13. package/lib/algo/jce/index.js +63 -0
  14. package/lib/algo/jce/jce.js +341 -0
  15. package/lib/algo/pb.js +159 -0
  16. package/lib/algo/protobuf.min.js +8 -0
  17. package/lib/algo/tea.js +121 -0
  18. package/lib/client-ext.js +312 -0
  19. package/lib/client-net.js +147 -0
  20. package/lib/client.js +594 -0
  21. package/lib/common.js +252 -0
  22. package/lib/core/friendlist.js +415 -0
  23. package/lib/core/nessy.js +148 -0
  24. package/lib/core/ref.d.ts +1 -0
  25. package/lib/core/sysmsg.js +388 -0
  26. package/lib/core/troop.js +586 -0
  27. package/lib/device.js +181 -0
  28. package/lib/exception.js +57 -0
  29. package/lib/message/builder.js +1093 -0
  30. package/lib/message/chat.js +276 -0
  31. package/lib/message/face.js +293 -0
  32. package/lib/message/file.js +425 -0
  33. package/lib/message/history.js +73 -0
  34. package/lib/message/image.js +533 -0
  35. package/lib/message/multi.js +242 -0
  36. package/lib/message/music.js +172 -0
  37. package/lib/message/parser.js +774 -0
  38. package/lib/message/ptt.js +389 -0
  39. package/lib/oicq.js +427 -0
  40. package/lib/onlinepush.js +616 -0
  41. package/lib/ref.d.ts +177 -0
  42. package/lib/service.js +204 -0
  43. package/lib/wtlogin/ecdh.js +15 -0
  44. package/lib/wtlogin/login-password.js +215 -0
  45. package/lib/wtlogin/login-qrcode.js +249 -0
  46. package/lib/wtlogin/tlv.js +331 -0
  47. package/lib/wtlogin/writer.js +88 -0
  48. package/lib/wtlogin/wt.js +422 -0
  49. package/package.json +50 -0
  50. package/util.js +115 -0
@@ -0,0 +1,480 @@
1
+ "use strict";
2
+ const path = require("path");
3
+ const fs = require("fs");
4
+ const os = require("os");
5
+ const querystring = require("querystring");
6
+ const url = require("url");
7
+ const crypto = require("crypto");
8
+ const oicq = require("../");
9
+ const http = require("http");
10
+ const https = require("https");
11
+ const WebSocket = require("ws");
12
+ const filter = require("./filter");
13
+ const api = require("./api");
14
+ const transNotice = require("./cq-notice");
15
+
16
+ /**
17
+ * @type {oicq.ConfBot}
18
+ */
19
+ const config = {};
20
+
21
+ /**
22
+ * @type {oicq.Client}
23
+ */
24
+ let bot;
25
+
26
+ /**
27
+ * @type {WebSocket.Server}
28
+ */
29
+ let wss;
30
+
31
+ /**
32
+ * @type {Set<WebSocket>}
33
+ */
34
+ let websockets = new Set();
35
+
36
+ let account = 0, passdir = "", wsrCreated = false;
37
+
38
+ /**
39
+ * 启动
40
+ */
41
+ function startup(arg1, arg2) {
42
+ account = arg1;
43
+ Object.assign(config, arg2);
44
+ config.data_dir = path.join(os.homedir(), ".oicq");
45
+ passdir = path.join(os.homedir(), ".oicq", String(account));
46
+ console.log("已加载配置文件:", config);
47
+ if (config.enable_heartbeat && (config.use_ws || config.ws_reverse_url.length)) {
48
+ setInterval(()=>{
49
+ const json = JSON.stringify({
50
+ self_id: account,
51
+ time: parseInt(Date.now()/1000),
52
+ post_type: "meta_event",
53
+ meta_event_type: "heartbeat",
54
+ interval: config.heartbeat_interval,
55
+ })
56
+ websockets.forEach((ws)=>{
57
+ ws.send(json);
58
+ });
59
+ if (wss) {
60
+ wss.clients.forEach((ws)=>{
61
+ ws.send(json);
62
+ });
63
+ }
64
+ }, config.heartbeat_interval);
65
+ }
66
+ filter.init(config.event_filter);
67
+ createBot();
68
+ createServer();
69
+ setTimeout(botLogin, 500);
70
+ }
71
+
72
+ /**
73
+ * 输入密码
74
+ */
75
+ function inputPassword() {
76
+ console.log("请输入密码(扫码登录直接按回车):");
77
+ process.stdin.once("data", (input)=>{
78
+ input = input.toString().trim();
79
+ if (!input.length) {
80
+ fs.writeFileSync(path.join(passdir, "password"), "", {mode: 0o600});
81
+ return bot.login();
82
+ }
83
+ const password = crypto.createHash("md5").update(input).digest();
84
+ fs.writeFileSync(path.join(passdir, "password"), password, {mode: 0o600});
85
+ bot.login(password);
86
+ })
87
+ }
88
+
89
+ function botLogin() {
90
+ const filepath = path.join(passdir, "password");
91
+ try {
92
+ const password = fs.readFileSync(filepath);
93
+ bot.login(password.length ? password : null);
94
+ } catch {
95
+ inputPassword();
96
+ }
97
+ }
98
+
99
+ /**
100
+ * 创建bot
101
+ */
102
+ function createBot() {
103
+ bot = oicq.createClient(account, config);
104
+ api.setBot(bot, config.rate_limit_interval);
105
+ bot.on("system.login.slider", ()=>{
106
+ process.stdin.once("data", (input)=>{
107
+ input = String(input).trim().replace("ticket:", "").trim().replace(/"/g, "");
108
+ bot.sliderLogin(input);
109
+ });
110
+ });
111
+ bot.on("system.login.qrcode", ()=>{
112
+ bot.logger.mark("扫码完成后回车登录。");
113
+ process.stdin.once("data", ()=>{
114
+ bot.login();
115
+ });
116
+ });
117
+ bot.on("system.login.device", ()=>{
118
+ bot.logger.mark("验证完成后回车登录。");
119
+ process.stdin.once("data", ()=>{
120
+ bot.login();
121
+ });
122
+ });
123
+ bot.on("system.login.error", (data)=>{
124
+ if (data.code === -2)
125
+ return bot.login();
126
+ if (data.message.includes("密码错误"))
127
+ inputPassword();
128
+ else
129
+ bot.terminate();
130
+ });
131
+
132
+ bot.on("system.online", ()=>{
133
+ loop();
134
+ dipatch({
135
+ self_id: account,
136
+ time: parseInt(Date.now()/1000),
137
+ post_type: "meta_event",
138
+ meta_event_type: "lifecycle",
139
+ sub_type: "enable",
140
+ });
141
+ if (!wsrCreated)
142
+ createReverseWS();
143
+ });
144
+ bot.on("system.offline", (data)=>{
145
+ dipatch({
146
+ self_id: account,
147
+ time: parseInt(Date.now()/1000),
148
+ post_type: "meta_event",
149
+ meta_event_type: "lifecycle",
150
+ sub_type: "disable",
151
+ });
152
+ });
153
+
154
+ bot.on("request", dipatch);
155
+ bot.on("notice", (data)=>{
156
+ if (config.use_cqhttp_notice)
157
+ transNotice(data);
158
+ dipatch(data);
159
+ });
160
+ bot.on("message", (data)=>{
161
+ if (config.post_message_format === "string")
162
+ data.message = data.raw_message;
163
+ dipatch(data);
164
+ });
165
+ }
166
+
167
+ /**
168
+ * 分发事件
169
+ */
170
+ function dipatch(event) {
171
+ if (!filter.assert(event))
172
+ return;
173
+ const json = JSON.stringify(event);
174
+ const options = {
175
+ method: 'POST',
176
+ timeout: config.post_timeout,
177
+ headers: {
178
+ 'Content-Type': 'application/json',
179
+ "X-Self-ID": String(account),
180
+ "User-Agent": "OneBot"
181
+ }
182
+ }
183
+ if (config.secret) {
184
+ options.headers["X-Signature"] = "sha1=" + crypto.createHmac("sha1", config.secret.toString()).update(json).digest("hex");
185
+ }
186
+ for (let url of config.post_url) {
187
+ const protocol = url.startsWith("https") ? https: http;
188
+ try {
189
+ const req = protocol.request(url, options, (res)=>{
190
+ bot.logger.debug(`POST(${url})上报事件: ` + json);
191
+ onHttpRes(event, res);
192
+ }).on("error", (e)=>{
193
+ bot.logger.error(`POST(${url})上报失败:` + e.message);
194
+ });
195
+ req.end(json);
196
+ } catch (e) {
197
+ bot.logger.error(`POST(${url})上报失败:` + e.message);
198
+ }
199
+ }
200
+ if (wss) {
201
+ wss.clients.forEach((ws)=>{
202
+ bot.logger.debug(`正向WS上报事件: ` + json);
203
+ ws.send(json);
204
+ });
205
+ }
206
+ websockets.forEach((ws)=>{
207
+ bot.logger.debug(`反向WS(${ws.url})上报事件: ` + json);
208
+ ws.send(json);
209
+ });
210
+ }
211
+
212
+ /**
213
+ * 创建http&ws服务器
214
+ */
215
+ function createServer() {
216
+ if (!config.use_http && !config.use_ws)
217
+ return;
218
+ const server = http.createServer((req, res)=>{
219
+ if (!config.use_http)
220
+ return res.writeHead(404).end();
221
+ if (req.method === 'OPTIONS' && config.enable_cors) {
222
+ return res.writeHead(200, {
223
+ 'Access-Control-Allow-Origin': '*',
224
+ 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
225
+ 'Access-Control-Allow-Headers': 'Content-Type, authorization'
226
+ }).end();
227
+ }
228
+ if (config.access_token) {
229
+ if (!req.headers["authorization"]) {
230
+ const access_token = querystring.parse(url.parse(req.url).query).access_token;
231
+ if (access_token)
232
+ req.headers["authorization"] = access_token;
233
+ else
234
+ return res.writeHead(401).end();
235
+ }
236
+ if (!req.headers["authorization"].includes(config.access_token))
237
+ return res.writeHead(403).end();
238
+ }
239
+ onHttpReq(req, res);
240
+ });
241
+ if (config.use_ws) {
242
+ wss = new WebSocket.Server({server});
243
+ wss.on("error", ()=>{});
244
+ wss.on("connection", (ws, req)=>{
245
+ ws.on("error", ()=>{});
246
+ if (config.access_token) {
247
+ if (req.url) {
248
+ const url = new URL('http://www.example.com/' + req.url);
249
+ const accessToken = url.searchParams.get('access_token');
250
+ if (accessToken) {
251
+ req.headers["authorization"] = accessToken;
252
+ }
253
+ }
254
+ if (!req.headers["authorization"] || !req.headers["authorization"].includes(config.access_token))
255
+ return ws.close(1002);
256
+ }
257
+ onWSOpen(ws);
258
+ });
259
+ }
260
+ server.listen(config.port, config.host, ()=>{
261
+ bot.logger.info(`开启http服务器成功,监听${server.address().address}:${server.address().port}`);
262
+ }).on("error", (e)=>{
263
+ bot.logger.error(e.message);
264
+ bot.logger.error("开启http服务器失败,进程退出。");
265
+ process.exit(0);
266
+ })
267
+ }
268
+
269
+ /**
270
+ * ws连接建立
271
+ * @param {WebSocket} ws
272
+ */
273
+ function onWSOpen(ws) {
274
+ ws.on("message", (data)=>{
275
+ onWSMessage(ws, data);
276
+ });
277
+ ws.send(JSON.stringify({
278
+ self_id: account,
279
+ time: parseInt(Date.now()/1000),
280
+ post_type: "meta_event",
281
+ meta_event_type: "lifecycle",
282
+ sub_type: "connect",
283
+ }));
284
+ ws.send(JSON.stringify({
285
+ self_id: account,
286
+ time: parseInt(Date.now()/1000),
287
+ post_type: "meta_event",
288
+ meta_event_type: "lifecycle",
289
+ sub_type: "enable",
290
+ }));
291
+ }
292
+
293
+ /**
294
+ * 创建反向ws
295
+ */
296
+ function createReverseWS() {
297
+ wsrCreated = true;
298
+ const headers = {
299
+ "X-Self-ID": String(account),
300
+ "X-Client-Role": "Universal",
301
+ "User-Agent": "OneBot"
302
+ };
303
+ if (config.access_token)
304
+ headers.Authorization = "Bearer " + config.access_token;
305
+ for (let url of config.ws_reverse_url) {
306
+ createWSClient(url, headers);
307
+ }
308
+ }
309
+ function createWSClient(url, headers) {
310
+ try {
311
+ const ws = new WebSocket(url, {headers});
312
+ ws.on("error", ()=>{});
313
+ ws.on("open", ()=>{
314
+ bot.logger.info(`反向ws连接(${url})连接成功。`);
315
+ websockets.add(ws);
316
+ onWSOpen(ws);
317
+ });
318
+ ws.on("close", (code)=>{
319
+ websockets.delete(ws);
320
+ if ((code === 1000 & config.ws_reverse_reconnect_on_code_1000 === false) || config.ws_reverse_reconnect_interval >= 0 === false)
321
+ return bot.logger.info(`反向ws连接(${url})被关闭,关闭码${code}。不再重连。`);
322
+ bot.logger.error(`反向ws连接(${url})被关闭,关闭码${code},将在${config.ws_reverse_reconnect_interval}毫秒后尝试连接。`);
323
+ setTimeout(()=>{
324
+ createWSClient(url, headers);
325
+ }, config.ws_reverse_reconnect_interval);
326
+ });
327
+ } catch (e) {
328
+ bot.logger.error(e.message);
329
+ }
330
+ }
331
+
332
+ /**
333
+ * 收到http响应
334
+ * @param {http.ServerResponse} res
335
+ */
336
+ function onHttpRes(event, res) {
337
+ let data = [];
338
+ res.on("data", (chunk)=>data.push(chunk));
339
+ res.on("end", ()=>{
340
+ data = Buffer.concat(data).toString();
341
+ debug(`收到HTTP响应:${res.statusCode} ` + data);
342
+ try {
343
+ data = JSON.parse(data);
344
+ api.quickOperate(event, data);
345
+ } catch (e) {}
346
+ })
347
+ }
348
+
349
+ /**
350
+ * 收到http请求
351
+ * @param {http.ClientRequest} req
352
+ * @param {http.ServerResponse} res
353
+ */
354
+ async function onHttpReq(req, res) {
355
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
356
+ if (config.enable_cors)
357
+ res.setHeader("Access-Control-Allow-Origin", "*");
358
+ const qop = url.parse(req.url);
359
+ const action = qop.pathname.replace(/\//g, "");
360
+ if (req.method === "GET") {
361
+ debug(`收到GET请求: ` + req.url);
362
+ const params = querystring.parse(qop.query);
363
+ try {
364
+ const ret = await api.apply({action, params});
365
+ res.end(ret);
366
+ } catch (e) {
367
+ res.writeHead(404).end();
368
+ }
369
+ } else if (req.method === "POST") {
370
+ let data = [];
371
+ req.on("data", (chunk)=>data.push(chunk));
372
+ req.on("end", async()=>{
373
+ try {
374
+ data = Buffer.concat(data).toString();
375
+ debug(`收到POST请求: ` + data);
376
+ let params, ct = req.headers["content-type"];
377
+ if (!ct || ct.includes("json"))
378
+ params = data ? JSON.parse(data) : {};
379
+ else if (ct && ct.includes("x-www-form-urlencoded"))
380
+ params = querystring.parse(data);
381
+ else
382
+ return res.writeHead(406).end();
383
+ const ret = await api.apply({action, params});
384
+ res.end(ret);
385
+ } catch (e) {
386
+ if (e instanceof api.NotFoundError)
387
+ res.writeHead(404).end();
388
+ else
389
+ res.writeHead(400).end();
390
+ }
391
+ });
392
+ } else {
393
+ res.writeHead(405).end();
394
+ }
395
+ }
396
+
397
+ /**
398
+ * 收到ws消息
399
+ * @param {WebSocket} ws
400
+ */
401
+ async function onWSMessage(ws, data) {
402
+ debug(`收到WS消息: ` + data);
403
+ try {
404
+ data = JSON.parse(data);
405
+ if (
406
+ data.action === ".handle_quick_operation" ||
407
+ data.action === ".handle_quick_operation_async" ||
408
+ data.action === ".handle_quick_operation_rate_limited"
409
+ ) {
410
+ api.handleQuickOperation(data);
411
+ var ret = JSON.stringify({
412
+ retcode: 1,
413
+ status: "async",
414
+ data: null,
415
+ echo: data.echo
416
+ });
417
+ } else {
418
+ var ret = await api.apply(data);
419
+ }
420
+ ws.send(ret);
421
+ } catch (e) {
422
+ if (e instanceof api.NotFoundError)
423
+ var retcode = 1404;
424
+ else
425
+ var retcode = 1400;
426
+ ws.send(JSON.stringify({
427
+ retcode: retcode,
428
+ status: "failed",
429
+ data: null,
430
+ echo: data.echo
431
+ }));
432
+ }
433
+ }
434
+
435
+ function debug(msg) {
436
+ if (bot && bot.logger)
437
+ bot.logger.debug(msg);
438
+ else
439
+ console.log(msg);
440
+ }
441
+
442
+ function loop() {
443
+ const help = `※你已成功登录,此控制台有简单的指令可用于调试。
444
+ ※发言: send <target> <message>
445
+ ※下线结束程序: bye
446
+ ※执行任意代码: eval <code>`;
447
+ console.log(help);
448
+ process.stdin.on("data", async (input) => {
449
+ input = input.toString().trim();
450
+ if (!input) return;
451
+ const cmd = input.split(" ")[0];
452
+ const param = input.replace(cmd, "").trim();
453
+ switch (cmd) {
454
+ case "bye":
455
+ bot.logout().then(process.exit);
456
+ break;
457
+ case "send":
458
+ const abc = param.split(" ");
459
+ const target = parseInt(abc[0]);
460
+ if (bot.gl.has(target))
461
+ bot.sendGroupMsg(target, abc[1]);
462
+ else
463
+ bot.sendPrivateMsg(target, abc[1]);
464
+ break;
465
+ case "eval":
466
+ try {
467
+ let res = await eval(param);
468
+ console.log("Result:", res);
469
+ } catch (e) {
470
+ console.log(e);
471
+ }
472
+ break;
473
+ default:
474
+ console.log(help);
475
+ break;
476
+ }
477
+ }).on("error", () => { });
478
+ }
479
+
480
+ module.exports = startup;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /**
3
+ * @param {import("../").FriendNoticeEventData | import("../").GroupNoticeEventData} data
4
+ */
5
+ module.exports = function(data) {
6
+ if (data.sub_type === "poke") {
7
+ data.notice_type = "notify";
8
+ data.target_id = data.user_id;
9
+ data.user_id = data.operator_id;
10
+ data.operator_id = undefined;
11
+ return;
12
+ }
13
+ if (data.notice_type === "friend") {
14
+ if (data.sub_type === "increase")
15
+ data.sub_type = undefined, data.notice_type = "friend_add";
16
+ else if (data.sub_type === "recall")
17
+ data.sub_type = undefined, data.notice_type = "friend_recall";
18
+ } else if (data.notice_type === "group") {
19
+ if (data.sub_type === "increase") {
20
+ data.sub_type = undefined, data.notice_type = "group_increase";
21
+ } else if (data.sub_type === "decrease") {
22
+ data.notice_type = "group_decrease";
23
+ if (data.operator_id === data.user_id)
24
+ data.sub_type = "leave";
25
+ else if (data.self_id === data.user_id)
26
+ data.sub_type = "kick_me";
27
+ else
28
+ data.sub_type = "kick";
29
+ } else if (data.sub_type === "recall") {
30
+ data.sub_type = undefined, data.notice_type = "group_recall";
31
+ } else if (data.sub_type === "ban") {
32
+ data.notice_type = "group_ban";
33
+ data.sub_type = data.duration ? "ban" : "lift_ban";
34
+ } else if (data.sub_type === "admin") {
35
+ data.notice_type = "group_admin";
36
+ data.sub_type = data.set ? "set" : "unset";
37
+ }
38
+ }
39
+ };
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ const fs = require("fs");
3
+ let filter, event;
4
+
5
+ function init(filepath) {
6
+ if (filepath) {
7
+ try {
8
+ filter = fs.readFileSync(filepath, "utf8");
9
+ filter = JSON.parse(filter);
10
+ console.log("已启用事件过滤器。")
11
+ } catch (e) {
12
+ console.log(e.message);
13
+ console.log("加载事件过滤器失败,进程退出。");
14
+ process.exit(0);
15
+ }
16
+ }
17
+ }
18
+
19
+ function _exec(o = filter, op = "and", field) {
20
+
21
+ if (["and", "not", "or"].includes(op)) {
22
+ if (Array.isArray(o)) {
23
+ for (let rule of o) {
24
+ let matched = _exec(rule, "and", field);
25
+ if (!matched && op === "and")
26
+ return false;
27
+ if (matched && op === "not")
28
+ return false;
29
+ if (matched && op === "or")
30
+ return true;
31
+ }
32
+ return op !== "or" || !o.length;
33
+ } else if (typeof o === "object" && o !== null) {
34
+ for (let k in o) {
35
+ let matched;
36
+ if (k.startsWith("."))
37
+ matched = _exec(o[k], k.substr(1), field);
38
+ else
39
+ matched = _exec(o[k], "eq", k);
40
+ if (!matched && op === "and")
41
+ return false;
42
+ if (matched && op === "not")
43
+ return false;
44
+ if (matched && op === "or")
45
+ return true;
46
+ }
47
+ return op !== "or" || !Object.keys(o).length;
48
+ } else {
49
+ return false;
50
+ }
51
+ }
52
+
53
+ if (typeof o === "object" && o !== null && !Array.isArray(o))
54
+ return _exec(o, "and", field);
55
+
56
+ if (op === "eq") {
57
+ return o === event[field];
58
+ }
59
+
60
+ if (op === "neq") {
61
+ return o !== event[field];
62
+ }
63
+
64
+ if (op === "in") {
65
+ return o.includes(event[field]);
66
+ }
67
+
68
+ if (op === "contains") {
69
+ return event[field].includes(o);
70
+ }
71
+
72
+ if (op === "regex") {
73
+ if (o.startsWith("/"))
74
+ o = o.substr(1);
75
+ const split = o.split("/");
76
+ const regex = new RegExp(split[0], split[1]);
77
+ return !!event[field].match(regex);
78
+ }
79
+
80
+ return true;
81
+ }
82
+
83
+ function test() {
84
+ init("../filter.json");
85
+ const e = {
86
+ self_id: 123456,
87
+ time: 1606094532,
88
+ post_type: "message",
89
+ message_type: "group",
90
+ sub_type: "normal",
91
+ message_id: "REAq4xY6N/UAAAJIIjI65l+7DsQ=",
92
+ group_id: 123456,
93
+ group_name: "ddddd",
94
+ user_id: 123456,
95
+ anonymous: null,
96
+ message: "data",
97
+ raw_message: "data",
98
+ font: "微软雅黑",
99
+ sender: {
100
+ user_id: 123456,
101
+ nickname: "123456",
102
+ card: "",
103
+ sex: "female",
104
+ age: 115,
105
+ area: "上海",
106
+ level: 2,
107
+ role: "member",
108
+ title: ""
109
+ }
110
+ };
111
+ console.log(assert(e));
112
+ }
113
+ // test()
114
+
115
+ function assert(e) {
116
+ if (!filter)
117
+ return true;
118
+ event = e;
119
+ try {
120
+ return _exec();
121
+ } catch {
122
+ return false;
123
+ }
124
+ }
125
+
126
+ module.exports = {
127
+ init, assert
128
+ };
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ const path = require("path");
3
+ const fs = require("fs");
4
+ const os = require("os");
5
+
6
+ const dir = path.join(os.homedir(), ".oicq");
7
+ if (!fs.existsSync(dir))
8
+ fs.mkdirSync(dir);
9
+
10
+ const confpath = path.join(dir, "config.js");
11
+ if (!fs.existsSync(confpath)) {
12
+ fs.copyFileSync(path.join(__dirname, "config.sample.js"), confpath);
13
+ console.log(`
14
+ 配置文件不存在,已帮你自动生成,请修改后再次启动程序。
15
+ 配置文件在:${confpath}
16
+ `);
17
+ process.exit(0);
18
+ }
19
+
20
+ const help = `
21
+ Usage: oicq <account>
22
+ Example: oicq 147258369
23
+ `;
24
+
25
+ const account = parseInt(process.argv[process.argv.length - 1]);
26
+ if (account > 10000 && account < 0xffffffff) {
27
+ process.title = "OICQ/OneBot - " + account;
28
+ console.log(`
29
+ *******************************************************************
30
+ * 欢迎使用 node-onebot
31
+ * 你可以将本程序作为一个无头机器人,或利用本程序进行调试
32
+ * Docs: https://github.com/takayama-lily/oicq/tree/master/http-api
33
+ *******************************************************************
34
+ `);
35
+ const config = require(confpath);
36
+ require("./core")(account, Object.assign(config.general, config[account]));
37
+ } else {
38
+ console.log(help);
39
+ }