🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

oicq

Package Overview
Dependencies
Maintainers
1
Versions
176
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

oicq - npm Package Compare versions

Comparing version
2.3.0
to
2.3.1
+1
-1
lib/client.d.ts

@@ -166,3 +166,3 @@ /// <reference types="node" />

sex: Gender;
age: number; /** 配置 */
age: number;
area: string;

@@ -169,0 +169,0 @@ }>;

@@ -25,4 +25,10 @@ /** 调用API时可能出现的错误 */

NoUploadChannel = -130,
/** 不支持的file类型(没有流) */
HighwayFileTypeError = -140,
/** 文件安全校验未通过不存在 */
UnsafeFile = -150,
/** 离线(私聊)文件不存在 */
OfflineFileNotExists = -160,
/** 群文件不存在(无法转发) */
GroupFileNotExists = -170,
/** 获取视频中的图片失败 */

@@ -29,0 +35,0 @@ FFmpegVideoThumbError = -210,

@@ -30,4 +30,10 @@ "use strict";

ErrorCode[ErrorCode["NoUploadChannel"] = -130] = "NoUploadChannel";
/** 不支持的file类型(没有流) */
ErrorCode[ErrorCode["HighwayFileTypeError"] = -140] = "HighwayFileTypeError";
/** 文件安全校验未通过不存在 */
ErrorCode[ErrorCode["UnsafeFile"] = -150] = "UnsafeFile";
/** 离线(私聊)文件不存在 */
ErrorCode[ErrorCode["OfflineFileNotExists"] = -160] = "OfflineFileNotExists";
/** 群文件不存在(无法转发) */
ErrorCode[ErrorCode["GroupFileNotExists"] = -170] = "GroupFileNotExists";
/** 获取视频中的图片失败 */

@@ -34,0 +40,0 @@ ErrorCode[ErrorCode["FFmpegVideoThumbError"] = -210] = "FFmpegVideoThumbError";

/// <reference types="node" />
import { pb } from "./core";
import { Gender } from "./common";
import { Sendable, PrivateMessage, MusicPlatform, Quotable } from "./message";
import { Sendable, PrivateMessage, MusicPlatform, Quotable, FileElem } from "./message";
import { Contactable } from "./internal";

@@ -60,2 +60,3 @@ import { MessageRet } from "./events";

setGroupInvite(gid: number, seq: number, yes?: boolean, block?: boolean): Promise<boolean>;
getFileInfo(fid: string): Promise<Omit<FileElem, "type"> & Record<"url", string>>;
/** 获取离线文件下载地址 */

@@ -95,6 +96,8 @@ getFileUrl(fid: string): Promise<string>;

*/
sendFile(file: string | Buffer, filename?: string, callback?: (percentage: string) => void): Promise<string>;
sendFile(file: string | Buffer | Uint8Array, filename?: string, callback?: (percentage: string) => void): Promise<string>;
/** 撤回离线文件 */
recallFile(fid: string): Promise<boolean>;
/** 转发离线文件 */
forwardFile(fid: string): Promise<string>;
}
export {};

@@ -248,4 +248,3 @@ "use strict";

}
/** 获取离线文件下载地址 */
async getFileUrl(fid) {
async getFileInfo(fid) {
const body = core_1.pb.encode({

@@ -270,4 +269,15 @@ 1: 1200,

url = `http://${obj[30]}:${obj[40]}` + url;
return url;
return {
name: String(rsp[40][7]),
fid: String(rsp[40][6]),
md5: rsp[40][100].toHex(),
size: rsp[40][3],
duration: rsp[40][4],
url,
};
}
/** 获取离线文件下载地址 */
async getFileUrl(fid) {
return (await this.getFileInfo(fid)).url;
}
}

@@ -379,3 +389,5 @@ exports.User = User;

let filesize, filemd5, filesha, filestream;
if (file instanceof Buffer) {
if (file instanceof Uint8Array) {
if (!Buffer.isBuffer(file))
file = Buffer.from(file);
filesize = file.length;

@@ -415,41 +427,45 @@ filemd5 = (0, common_1.md5)(file), filesha = (0, common_1.sha)(file);

const rsp1700 = core_1.pb.decode(payload)[19];
if (rsp1700[10] !== 0)
(0, errors_1.drop)(rsp1700[10], rsp1700[20]);
const fid = rsp1700[90].toBuffer();
const ext = core_1.pb.encode({
1: 100,
2: 2,
100: {
if (!rsp1700[110]) {
const ext = core_1.pb.encode({
1: 100,
2: 2,
100: {
1: 3,
100: this.c.uin,
200: this.uid,
400: 0,
700: payload,
100: {
1: 3,
100: this.c.uin,
200: this.uid,
400: 0,
700: payload,
},
200: {
100: filesize,
200: filemd5,
300: filesha,
400: filemd5,
600: fid,
700: rsp1700[220].toBuffer(),
},
300: {
100: 2,
200: String(this.c.apk.subid),
300: 2,
400: "d92615c5",
600: 4,
},
400: {
100: filename,
},
},
200: {
100: filesize,
200: filemd5,
300: filesha,
400: filemd5,
600: fid,
700: rsp1700[220].toBuffer(),
},
300: {
100: 2,
200: String(this.c.apk.subid),
300: 2,
400: "d92615c5",
600: 4,
},
400: {
100: filename,
},
},
200: 1
});
await internal_1.highwayHttpUpload.call(this.c, filestream, {
md5: filemd5,
size: filesize,
cmdid: internal_1.CmdID.OfflineFile,
ext, callback
});
200: 1
});
await internal_1.highwayHttpUpload.call(this.c, filestream, {
md5: filemd5,
size: filesize,
cmdid: internal_1.CmdID.OfflineFile,
ext, callback
});
}
const body800 = core_1.pb.encode({

@@ -499,3 +515,40 @@ 1: 800,

}
/** 转发离线文件 */
async forwardFile(fid) {
const body = core_1.pb.encode({
1: 700,
2: 0,
9: {
10: this.c.uin,
20: this.uid,
30: fid
},
101: 3,
102: 104,
200: 1,
});
const payload = await this.c.sendUni("OfflineFilleHandleSvr.pb_ftn_CMD_REQ_APPLY_FORWARD_FILE-700", body);
const rsp = core_1.pb.decode(payload)[9];
const new_fid = rsp[50];
const ticket = rsp[60];
if (rsp[10] !== 0)
(0, errors_1.drop)(rsp[10], rsp[20]);
const info = await this.getFileInfo(fid);
const proto3 = {
2: {
1: {
1: 0,
3: new_fid,
4: Buffer.from(info.md5, "hex"),
5: info.name,
6: info.size,
9: 1,
57: ticket
}
}
};
await this._sendMsg(proto3, `[文件:${info.name}]`, true);
return String(new_fid);
}
}
exports.Friend = Friend;

@@ -78,2 +78,9 @@ /// <reference types="node" />

upload(file: string | Buffer | Uint8Array, pid?: string, name?: string, callback?: (percentage: string) => void): Promise<GfsFileStat>;
/**
* 将文件转发到当前群
* @param stat 另一个群中的文件属性()
* @param pid 转发后的目录(默认根目录)
* @param name 转发后的文件名(默认不变)
*/
forward(stat: GfsFileStat, pid?: string, name?: string): Promise<GfsFileStat>;
/** 获取文件下载地址 */

@@ -80,0 +87,0 @@ download(fid: string): Promise<Omit<FileElem, "type"> & {

@@ -359,2 +359,31 @@ "use strict";

}
/**
* 将文件转发到当前群
* @param stat 另一个群中的文件属性()
* @param pid 转发后的目录(默认根目录)
* @param name 转发后的文件名(默认不变)
*/
async forward(stat, pid = "/", name) {
const body = core_1.pb.encode({
1: {
1: this.gid,
2: 3,
3: 102,
4: 5,
5: String(pid),
6: String(name || stat.name),
7: "/storage/emulated/0/Pictures/files/s/" + (name || stat.name),
8: Number(stat.size),
9: Buffer.from(stat.sha1, "hex"),
11: Buffer.from(stat.md5, "hex"),
15: 1,
}
});
const payload = await this.c.sendOidb("OidbSvc.0x6d6_0", body);
const rsp = core_1.pb.decode(payload)[4][1];
checkRsp(rsp);
if (!rsp[10])
(0, errors_1.drop)(errors_1.ErrorCode.GroupFileNotExists, "文件不存在,无法被转发");
return await this._feed(String(rsp[7]), rsp[6]);
}
/** 获取文件下载地址 */

@@ -361,0 +390,0 @@ async download(fid) {

@@ -29,2 +29,3 @@ "use strict";

const crypto_1 = require("crypto");
const http_1 = __importDefault(require("http"));
const axios_1 = __importDefault(require("axios"));

@@ -106,2 +107,4 @@ const core_1 = require("../core");

throw new core_1.ApiRejection(errors_1.ErrorCode.NoUploadChannel, "没有上传通道,如果你刚刚登录,请等待几秒");
if (!readable)
throw new core_1.ApiRejection(errors_1.ErrorCode.HighwayFileTypeError, "不支持的file类型");
this.logger.debug(`highway ip:${ip} port:${port}`);

@@ -169,3 +172,4 @@ return new Promise((resolve, reject) => {

exports.highwayUpload = highwayUpload;
async function highwayHttpUpload(readable, obj) {
const agent = new http_1.default.Agent({ maxSockets: 10 });
function highwayHttpUpload(readable, obj) {
const ip = this.sig.bigdata.ip;

@@ -180,3 +184,4 @@ const port = this.sig.bigdata.port;

obj.ticket = this.sig.bigdata.sig_session;
const tasks = [];
const tasks = new Set();
const cancels = new Set();
let finished = 0;

@@ -218,4 +223,8 @@ readable.on("data", data => {

const task = new Promise((resolve, reject) => {
const c = axios_1.default.CancelToken.source();
cancels.add(c);
axios_1.default.post(url, buf, {
responseType: "arraybuffer",
httpAgent: agent,
cancelToken: c.token,
headers: {

@@ -241,10 +250,18 @@ "Content-Length": String(buf.length)

++finished;
percentage = (finished / tasks.length * 100).toFixed(2);
percentage = (finished / tasks.size * 100).toFixed(2);
this.logger.debug(`highway(http) chunk uploaded (${percentage}%)`);
if (typeof obj.callback === "function" && percentage)
obj.callback(percentage);
if (rsp[7]?.toBuffer().length > 0 && finished < tasks.size) {
cancels.forEach(c => c.cancel());
this.logger.debug(`highway(http) chunk uploaded (100.00%)`);
if (typeof obj.callback === "function")
obj.callback("100.00");
}
if (!rsp[7]?.toBuffer().length && finished >= tasks.size)
reject(new core_1.ApiRejection(errors_1.ErrorCode.UnsafeFile, "文件校验未通过,上传失败"));
resolve(undefined);
});
}).catch(reject);
});
tasks.push(task);
tasks.add(task);
}

@@ -255,5 +272,11 @@ offset += data.length;

readable.on("err", reject)
.on("end", () => resolve(Promise.all(tasks)));
.on("end", () => {
Promise.all(tasks).then(resolve).catch(err => {
if (err instanceof axios_1.default.Cancel === false)
reject(err);
resolve(undefined);
});
});
});
}
exports.highwayHttpUpload = highwayHttpUpload;
{
"name": "oicq",
"version": "2.3.0",
"upday": "2022/6/19",
"version": "2.3.1",
"upday": "2022/6/21",
"description": "QQ protocol!",

@@ -29,3 +29,3 @@ "main": "lib/index.js",

"dependencies": {
"axios": "^0.24.0",
"axios": "^0.27.2",
"log4js": "^6.3.0",

@@ -32,0 +32,0 @@ "long": "^4.0.0",

@@ -239,2 +239,3 @@ # oicq

| sendFile() | 发送文件 |
| forwardFile()| 转发文件 |
| recallFile() | 撤回文件 |

@@ -312,2 +313,3 @@

| upload() | 上传文件 |
| forward() | 转发文件 |
| download() | 获取下载链接 |

@@ -314,0 +316,0 @@