+1
-1
@@ -269,3 +269,3 @@ /// <reference types="node" /> | ||
| /** | ||
| * 触发system.offline.network事件后的重新登录间隔秒数,默认5(秒),不建议设置低于3(秒) | ||
| * 触发system.offline.network事件后的重新登录间隔秒数,默认8(秒),不建议设置过低 | ||
| * 设置为0则不会自动重连,然后你可以监听此事件自己处理 | ||
@@ -272,0 +272,0 @@ */ |
+4
-4
@@ -45,3 +45,3 @@ "use strict"; | ||
| cache_group_member: true, | ||
| reconn_interval: 5, | ||
| reconn_interval: 8, | ||
| data_dir: path.join(require?.main?.path || process.cwd(), "data"), | ||
@@ -356,7 +356,7 @@ ...conf, | ||
| async sendPrivateMsg(user_id, message, source) { | ||
| return this.pickFriend(user_id).sendMsg(message); | ||
| return this.pickFriend(user_id).sendMsg(message, source); | ||
| } | ||
| /** @cqhttp use group.sendMsg() */ | ||
| async sendGroupMsg(group_id, message, source) { | ||
| return this.pickGroup(group_id).sendMsg(message); | ||
| return this.pickGroup(group_id).sendMsg(message, source); | ||
| } | ||
@@ -529,3 +529,3 @@ /** @cqhttp use discuss.sendMsg() */ | ||
| _msgExists(from, type, seq, time) { | ||
| if ((0, common_1.timestamp)() - time >= 60 || time < this.stat.start_time) | ||
| if ((0, common_1.timestamp)() + this.sig.time_diff - time >= 60 || time < this.stat.start_time) | ||
| return true; | ||
@@ -532,0 +532,0 @@ const id = [from, type, seq].join("-"); |
@@ -11,2 +11,3 @@ /// <reference types="node" /> | ||
| declare const IS_ONLINE: unique symbol; | ||
| declare const LOGIN_LOCK: unique symbol; | ||
| declare const HEARTBEAT: unique symbol; | ||
@@ -63,2 +64,3 @@ export declare enum VerboseLevel { | ||
| private [IS_ONLINE]; | ||
| private [LOGIN_LOCK]; | ||
| private [ECDH]; | ||
@@ -88,4 +90,7 @@ private readonly [NET]; | ||
| }; | ||
| /** 心跳包 */ | ||
| hb480: Uint8Array; | ||
| /** 上次cookie刷新时间 */ | ||
| emp_time: number; | ||
| time_diff: number; | ||
| }; | ||
@@ -92,0 +97,0 @@ readonly pskey: { |
@@ -24,3 +24,3 @@ "use strict"; | ||
| }; | ||
| var _a, _b, _c, _d; | ||
| var _a, _b, _c, _d, _e; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -47,2 +47,3 @@ exports.BaseClient = exports.QrcodeResult = exports.ApiRejection = exports.VerboseLevel = void 0; | ||
| const IS_ONLINE = Symbol("IS_ONLINE"); | ||
| const LOGIN_LOCK = Symbol("LOGIN_LOCK"); | ||
| const HEARTBEAT = Symbol("HEARTBEAT"); | ||
@@ -80,6 +81,7 @@ var VerboseLevel; | ||
| this[_a] = false; | ||
| this[_b] = new ecdh_1.default; | ||
| this[_c] = new network_1.default; | ||
| // 存放包的回调函数 | ||
| this[_d] = new Map(); | ||
| this[_b] = false; | ||
| this[_c] = new ecdh_1.default; | ||
| this[_d] = new network_1.default; | ||
| // 回包的回调函数 | ||
| this[_e] = new Map(); | ||
| this.sig = { | ||
@@ -104,2 +106,3 @@ seq: (0, crypto_1.randomBytes)(4).readUInt32BE() & 0xfff, | ||
| }, | ||
| /** 心跳包 */ | ||
| hb480: (() => { | ||
@@ -115,3 +118,5 @@ const buf = Buffer.alloc(9); | ||
| })(), | ||
| /** 上次cookie刷新时间 */ | ||
| emp_time: 0, | ||
| time_diff: 0, | ||
| }; | ||
@@ -148,2 +153,3 @@ this.pskey = {}; | ||
| this.emit("internal.verbose", `${this[NET].remoteAddress}:${this[NET].remotePort} connected`, VerboseLevel.Mark); | ||
| syncTimeDiff.call(this); | ||
| }); | ||
@@ -341,3 +347,6 @@ this[NET].on("packet", packetListener.bind(this)); | ||
| } | ||
| }).catch(() => this.emit("internal.error.network", -2, "server is busy")); | ||
| }).catch((err) => { | ||
| this.emit("internal.verbose", err.message, VerboseLevel.Error); | ||
| this.emit("internal.error.network", -2, "server is busy"); | ||
| }); | ||
| } | ||
@@ -462,3 +471,3 @@ /** 扫码后调用此方法登录 */ | ||
| } | ||
| [(_a = IS_ONLINE, _b = ECDH, _c = NET, _d = HANDLERS, FN_NEXT_SEQ)]() { | ||
| [(_a = IS_ONLINE, _b = LOGIN_LOCK, _c = ECDH, _d = NET, _e = HANDLERS, FN_NEXT_SEQ)]() { | ||
| if (++this.sig.seq >= 0x8000) | ||
@@ -489,7 +498,11 @@ this.sig.seq = 1; | ||
| async [FN_SEND_LOGIN](cmd, body) { | ||
| if (this[IS_ONLINE] || this[LOGIN_LOCK]) | ||
| return; | ||
| const pkt = buildLoginPacket.call(this, cmd, body); | ||
| try { | ||
| this[LOGIN_LOCK] = true; | ||
| decodeLoginResponse.call(this, await this[FN_SEND](pkt)); | ||
| } | ||
| catch (e) { | ||
| this[LOGIN_LOCK] = false; | ||
| this.emit("internal.error.network", -2, "server is busy"); | ||
@@ -597,4 +610,6 @@ this.emit("internal.verbose", e.message, VerboseLevel.Error); | ||
| const retcode = buf.readInt32BE(8); | ||
| if (retcode !== 0) | ||
| if (retcode !== 0) { | ||
| this.emit("internal.error.token"); | ||
| throw new Error("unsuccessful retcode: " + retcode); | ||
| } | ||
| let offset = buf.readUInt32BE(12) + 12; | ||
@@ -622,2 +637,3 @@ let len = buf.readUInt32BE(offset); // length of cmd | ||
| this.statistics.recv_pkt_cnt++; | ||
| this[LOGIN_LOCK] = false; | ||
| try { | ||
@@ -638,5 +654,6 @@ const flag = pkt.readUInt8(4); | ||
| default: | ||
| this.emit("internal.error.token"); | ||
| throw new Error("unknown flag:" + flag); | ||
| } | ||
| const sso = await parseSso(decrypted); | ||
| const sso = await parseSso.call(this, decrypted); | ||
| this.emit("internal.verbose", `recv:${sso.cmd} seq:${sso.seq}`, VerboseLevel.Debug); | ||
@@ -687,2 +704,3 @@ if (this[HANDLERS].has(sso.seq)) | ||
| this[HEARTBEAT] = setInterval(async () => { | ||
| syncTimeDiff.call(this); | ||
| if (typeof this.heartbeat === "function") | ||
@@ -705,2 +723,11 @@ await this.heartbeat(); | ||
| } | ||
| function syncTimeDiff() { | ||
| const pkt = buildLoginPacket.call(this, "Client.CorrectTime", constants_1.BUF4, 0); | ||
| this[FN_SEND](pkt).then(buf => { | ||
| try { | ||
| this.sig.time_diff = buf.readInt32BE() - (0, constants_1.timestamp)(); | ||
| } | ||
| catch { } | ||
| }).catch(constants_1.NOOP); | ||
| } | ||
| async function refreshToken() { | ||
@@ -707,0 +734,0 @@ if (!this.isOnline() || (0, constants_1.timestamp)() - this.sig.emp_time < 14000) |
@@ -7,2 +7,4 @@ /// <reference types="node" /> | ||
| export declare const BUF0: Buffer; | ||
| /** 4个0的buf */ | ||
| export declare const BUF4: Buffer; | ||
| /** 16个0的buf */ | ||
@@ -9,0 +11,0 @@ export declare const BUF16: Buffer; |
@@ -22,3 +22,3 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.hide = exports.lock = exports.int32ip2str = exports.timestamp = exports.sha = exports.md5 = exports.pipeline = exports.gzip = exports.unzip = exports.NOOP = exports.BUF16 = exports.BUF0 = void 0; | ||
| exports.hide = exports.lock = exports.int32ip2str = exports.timestamp = exports.sha = exports.md5 = exports.pipeline = exports.gzip = exports.unzip = exports.NOOP = exports.BUF16 = exports.BUF4 = exports.BUF0 = void 0; | ||
| const crypto_1 = require("crypto"); | ||
@@ -30,2 +30,4 @@ const util_1 = require("util"); | ||
| exports.BUF0 = Buffer.alloc(0); | ||
| /** 4个0的buf */ | ||
| exports.BUF4 = Buffer.alloc(4); | ||
| /** 16个0的buf */ | ||
@@ -32,0 +34,0 @@ exports.BUF16 = Buffer.alloc(16); |
@@ -64,3 +64,4 @@ "use strict"; | ||
| 1: 1, | ||
| 2: req | ||
| 2: req, | ||
| // 10: 3 | ||
| }); | ||
@@ -432,3 +433,4 @@ const payload = await this.c.sendUni("LongConn.OffPicUp", body); | ||
| 20: { | ||
| 2: 1 | ||
| 1: 0, | ||
| 2: rand | ||
| } | ||
@@ -435,0 +437,0 @@ }, |
@@ -21,5 +21,2 @@ "use strict"; | ||
| }; | ||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||
| return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
| }; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -29,5 +26,3 @@ exports.bindInternalListeners = void 0; | ||
| const path = __importStar(require("path")); | ||
| const jsqr_1 = __importDefault(require("jsqr")); | ||
| const pngjs_1 = require("pngjs"); | ||
| const qrcode_terminal_1 = __importDefault(require("qrcode-terminal")); | ||
| const core_1 = require("../core"); | ||
@@ -123,2 +118,23 @@ const common_1 = require("../common"); | ||
| } | ||
| function logQrcode(img) { | ||
| const png = pngjs_1.PNG.sync.read(img); | ||
| const color_reset = "\x1b[0m"; | ||
| const color_fg_blk = "\x1b[30m"; | ||
| const color_bg_blk = "\x1b[40m"; | ||
| const color_fg_wht = "\x1b[37m"; | ||
| const color_bg_wht = "\x1b[47m"; | ||
| for (let i = 36; i < png.height * 4 - 36; i += 24) { | ||
| let line = ""; | ||
| for (let j = 36; j < png.width * 4 - 36; j += 12) { | ||
| let r0 = png.data[i * png.width + j]; | ||
| let r1 = png.data[i * png.width + j + (png.width * 4 * 3)]; | ||
| let bgcolor = (r0 == 255) ? color_bg_wht : color_bg_blk; | ||
| let fgcolor = (r1 == 255) ? color_fg_wht : color_fg_blk; | ||
| line += `${fgcolor + bgcolor}\u2584`; | ||
| } | ||
| console.log(line + color_reset); | ||
| } | ||
| console.log(`${color_fg_blk + color_bg_wht} 请使用 手机QQ 扫描二维码 ${color_reset}`); | ||
| console.log(`${color_fg_blk + color_bg_wht} ${color_reset}`); | ||
| } | ||
| function qrcodeListener(image) { | ||
@@ -128,8 +144,6 @@ const file = path.join(this.dir, "qrcode.png"); | ||
| try { | ||
| const qrdata = pngjs_1.PNG.sync.read(image); | ||
| const qr = (0, jsqr_1.default)(new Uint8ClampedArray(qrdata.data), qrdata.width, qrdata.height); | ||
| qrcode_terminal_1.default.generate(qr.data, console.log); | ||
| logQrcode(image); | ||
| } | ||
| catch { } | ||
| this.logger.mark("请用手机QQ扫描二维码,若打印出错请打开:" + file); | ||
| this.logger.mark("二维码图片已保存到:" + file); | ||
| this.em("system.login.qrcode", { image }); | ||
@@ -155,4 +169,9 @@ }); | ||
| this.logger.mark("登录token过期"); | ||
| fs.unlink(path.join(this.dir, "token"), () => { | ||
| this.login(); | ||
| fs.unlink(path.join(this.dir, "token"), (err) => { | ||
| if (err) { | ||
| this.logger.fatal(err.message); | ||
| return; | ||
| } | ||
| this.logger.mark("3秒后重新连接"); | ||
| setTimeout(this.login.bind(this), 3000); | ||
| }); | ||
@@ -159,0 +178,0 @@ } |
@@ -170,4 +170,6 @@ /// <reference types="node" /> | ||
| dice(id?: number | undefined): MfaceElem; | ||
| /** mention@提及,频道中的AT第一个参数传入对方的tiny_id */ | ||
| at(qq: number | "all" | string, text?: string | undefined, dummy?: boolean | undefined): AtElem; | ||
| /** mention@提及 | ||
| * @param qq 全体成员:"all", 频道:tiny_id | ||
| */ | ||
| at(qq: number | string, text?: string | undefined, dummy?: boolean | undefined): AtElem; | ||
| /** 图片(支持http://,base64://) */ | ||
@@ -174,0 +176,0 @@ image(file: ImageElem["file"], cache?: boolean | undefined, timeout?: number | undefined, headers?: import("http").OutgoingHttpHeaders | undefined): ImageElem; |
@@ -42,12 +42,14 @@ "use strict"; | ||
| }, | ||
| /** mention@提及,频道中的AT第一个参数传入对方的tiny_id */ | ||
| /** mention@提及 | ||
| * @param qq 全体成员:"all", 频道:tiny_id | ||
| */ | ||
| at(qq, text, dummy) { | ||
| // 频道中的AT | ||
| if (Number(qq) < 0xffffffff === false) { | ||
| if (Number(qq) <= 0xffffffff || qq === "all") { | ||
| return { | ||
| type: "at", qq: 0, id: String(qq), text, dummy | ||
| type: "at", qq: Number(qq), text, dummy | ||
| }; | ||
| } | ||
| // 频道中的AT | ||
| return { | ||
| type: "at", qq: Number(qq), text, dummy | ||
| type: "at", qq: 0, id: String(qq), text, dummy | ||
| }; | ||
@@ -54,0 +56,0 @@ }, |
+12
-0
@@ -256,2 +256,14 @@ "use strict"; | ||
| 324: "/吃糖", | ||
| 325: "/惊吓", | ||
| 326: "/生气", | ||
| 327: "/加一", | ||
| 328: "/错号", | ||
| 329: "/对号", | ||
| 330: "/完成", | ||
| 331: "/明白", | ||
| 332: "/举牌牌", | ||
| 333: "/烟花", | ||
| 334: "/虎虎生威", | ||
| 335: "/绿马护体", | ||
| 336: "/豹富", | ||
| }; | ||
@@ -258,0 +270,0 @@ exports.pokemap = { |
+3
-6
| { | ||
| "name": "oicq", | ||
| "version": "2.2.1", | ||
| "upday": "2021/3/16", | ||
| "version": "2.2.2", | ||
| "upday": "2021/4/9", | ||
| "description": "QQ protocol!", | ||
@@ -30,8 +30,6 @@ "main": "lib/index.js", | ||
| "axios": "^0.24.0", | ||
| "jsqr": "^1.4.0", | ||
| "log4js": "^6.3.0", | ||
| "long": "^4.0.0", | ||
| "pngjs": "^6.0.0", | ||
| "probe-image-size": "^7.2.2", | ||
| "qrcode-terminal": "^0.12.0" | ||
| "probe-image-size": "^7.2.2" | ||
| }, | ||
@@ -42,3 +40,2 @@ "devDependencies": { | ||
| "@types/probe-image-size": "^7.0.1", | ||
| "@types/qrcode-terminal": "^0.12.0", | ||
| "@types/ws": "^8.2.0", | ||
@@ -45,0 +42,0 @@ "protobufjs": "^6.11.2", |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
539146
0.4%5
-28.57%6
-14.29%13512
0.54%- Removed
- Removed
- Removed
- Removed