mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
536 lines
23 KiB
TypeScript
536 lines
23 KiB
TypeScript
import { PacketHighwayClient } from "@/core/packet/highway/client";
|
||
import { PacketContext } from "@/core/packet/context/packetContext";
|
||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||
import FetchSessionKey from "@/core/packet/transformer/highway/FetchSessionKey";
|
||
import { int32ip2str, oidbIpv4s2HighwayIpv4s } from "@/core/packet/highway/utils";
|
||
import {
|
||
PacketMsgFileElement,
|
||
PacketMsgPicElement,
|
||
PacketMsgPttElement,
|
||
PacketMsgVideoElement
|
||
} from "@/core/packet/message/element";
|
||
import { ChatType, Peer } from "@/core";
|
||
import { calculateSha1, calculateSha1StreamBytes, computeMd5AndLengthWithLimit } from "@/core/packet/utils/crypto/hash";
|
||
import UploadGroupImage from "@/core/packet/transformer/highway/UploadGroupImage";
|
||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||
import * as proto from "@/core/packet/transformer/proto";
|
||
import * as trans from "@/core/packet/transformer";
|
||
import fs from "fs";
|
||
|
||
export const BlockSize = 1024 * 1024;
|
||
|
||
interface HighwayServerAddr {
|
||
ip: string
|
||
port: number
|
||
}
|
||
|
||
export interface PacketHighwaySig {
|
||
uin: string;
|
||
uid: string;
|
||
sigSession: Uint8Array | null
|
||
sessionKey: Uint8Array | null
|
||
serverAddr: HighwayServerAddr[]
|
||
}
|
||
|
||
export class PacketHighwayContext {
|
||
private readonly context: PacketContext;
|
||
protected sig: PacketHighwaySig;
|
||
protected logger: PacketLogger;
|
||
protected hwClient: PacketHighwayClient;
|
||
private cachedPrepareReq: Promise<void> | null = null;
|
||
|
||
constructor(context: PacketContext) {
|
||
this.context = context;
|
||
this.sig = {
|
||
uin: String(context.napcore.basicInfo.uin),
|
||
uid: context.napcore.basicInfo.uid,
|
||
sigSession: null,
|
||
sessionKey: null,
|
||
serverAddr: [],
|
||
};
|
||
this.logger = context.logger;
|
||
this.hwClient = new PacketHighwayClient(this.sig, context.logger);
|
||
}
|
||
|
||
private async checkAvailable() {
|
||
if (this.sig.sigSession === null || this.sig.sessionKey === null) {
|
||
if (this.cachedPrepareReq === null) {
|
||
this.cachedPrepareReq = this.prepareUpload().finally(() => {
|
||
this.cachedPrepareReq = null;
|
||
});
|
||
}
|
||
await this.cachedPrepareReq;
|
||
}
|
||
}
|
||
|
||
private async prepareUpload(): Promise<void> {
|
||
this.logger.debug('[Highway] on prepareUpload!');
|
||
const packet = FetchSessionKey.build();
|
||
const req = await this.context.client.sendOidbPacket(packet, true);
|
||
const rsp = FetchSessionKey.parse(req);
|
||
this.sig.sigSession = rsp.httpConn.sigSession;
|
||
this.sig.sessionKey = rsp.httpConn.sessionKey;
|
||
for (const info of rsp.httpConn.serverInfos) {
|
||
if (info.serviceType !== 1) continue;
|
||
for (const addr of info.serverAddrs) {
|
||
this.logger.debug(`[Highway PrepareUpload] server addr add: ${int32ip2str(addr.ip)}:${addr.port}`);
|
||
this.sig.serverAddr.push({
|
||
ip: int32ip2str(addr.ip),
|
||
port: addr.port
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
async uploadImage(peer: Peer, img: PacketMsgPicElement): Promise<void> {
|
||
await this.checkAvailable();
|
||
if (peer.chatType === ChatType.KCHATTYPEGROUP) {
|
||
await this.uploadGroupImage(+peer.peerUid, img);
|
||
} else if (peer.chatType === ChatType.KCHATTYPEC2C) {
|
||
await this.uploadC2CImage(peer.peerUid, img);
|
||
} else {
|
||
throw new Error(`[Highway] unsupported chatType: ${peer.chatType}`);
|
||
}
|
||
}
|
||
|
||
async uploadVideo(peer: Peer, video: PacketMsgVideoElement): Promise<void> {
|
||
await this.checkAvailable();
|
||
if (+(video.fileSize ?? 0) > 1024 * 1024 * 100) {
|
||
throw new Error(`[Highway] 视频文件过大: ${(+(video.fileSize ?? 0) / (1024 * 1024)).toFixed(2)} MB > 100 MB,请使用文件上传!`);
|
||
}
|
||
if (peer.chatType === ChatType.KCHATTYPEGROUP) {
|
||
await this.uploadGroupVideo(+peer.peerUid, video);
|
||
} else if (peer.chatType === ChatType.KCHATTYPEC2C) {
|
||
await this.uploadC2CVideo(peer.peerUid, video);
|
||
} else {
|
||
throw new Error(`[Highway] unsupported chatType: ${peer.chatType}`);
|
||
}
|
||
}
|
||
|
||
async uploadPtt(peer: Peer, ptt: PacketMsgPttElement): Promise<void> {
|
||
await this.checkAvailable();
|
||
if (peer.chatType === ChatType.KCHATTYPEGROUP) {
|
||
await this.uploadGroupPtt(+peer.peerUid, ptt);
|
||
} else if (peer.chatType === ChatType.KCHATTYPEC2C) {
|
||
await this.uploadC2CPtt(peer.peerUid, ptt);
|
||
} else {
|
||
throw new Error(`[Highway] unsupported chatType: ${peer.chatType}`);
|
||
}
|
||
}
|
||
|
||
async uploadFile(peer: Peer, file: PacketMsgFileElement): Promise<void> {
|
||
await this.checkAvailable();
|
||
if (peer.chatType === ChatType.KCHATTYPEGROUP) {
|
||
await this.uploadGroupFile(+peer.peerUid, file);
|
||
} else if (peer.chatType === ChatType.KCHATTYPEC2C) {
|
||
await this.uploadC2CFile(peer.peerUid, file);
|
||
} else {
|
||
throw new Error(`[Highway] unsupported chatType: ${peer.chatType}`);
|
||
}
|
||
}
|
||
|
||
private async uploadGroupImage(groupUin: number, img: PacketMsgPicElement): Promise<void> {
|
||
img.sha1 = Buffer.from(await calculateSha1(img.path)).toString('hex');
|
||
const req = UploadGroupImage.build(groupUin, img);
|
||
const resp = await this.context.client.sendOidbPacket(req, true);
|
||
const preRespData = UploadGroupImage.parse(resp);
|
||
const ukey = preRespData.upload.uKey;
|
||
if (ukey && ukey != "") {
|
||
this.logger.debug(`[Highway] uploadGroupImageReq get upload ukey: ${ukey}, need upload!`);
|
||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||
const sha1 = Buffer.from(index.info.fileSha1, 'hex');
|
||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||
const extend = new NapProtoMsg(proto.NTV2RichMediaHighwayExt).encode({
|
||
fileUuid: index.fileUuid,
|
||
uKey: ukey,
|
||
network: {
|
||
ipv4S: oidbIpv4s2HighwayIpv4s(preRespData.upload.ipv4S)
|
||
},
|
||
msgInfoBody: preRespData.upload.msgInfo.msgInfoBody,
|
||
blockSize: BlockSize,
|
||
hash: {
|
||
fileSha1: [sha1]
|
||
}
|
||
});
|
||
await this.hwClient.upload(
|
||
1004,
|
||
fs.createReadStream(img.path, { highWaterMark: BlockSize }),
|
||
img.size,
|
||
md5,
|
||
extend
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadGroupImageReq get upload invalid ukey ${ukey}, don't need upload!`);
|
||
}
|
||
img.msgInfo = preRespData.upload.msgInfo;
|
||
// img.groupPicExt = new NapProtoMsg(CustomFace).decode(preRespData.tcpUpload.compatQMsg)
|
||
}
|
||
|
||
private async uploadC2CImage(peerUid: string, img: PacketMsgPicElement): Promise<void> {
|
||
img.sha1 = Buffer.from(await calculateSha1(img.path)).toString('hex');
|
||
const req = trans.UploadPrivateImage.build(peerUid, img);
|
||
const resp = await this.context.client.sendOidbPacket(req, true);
|
||
const preRespData = trans.UploadPrivateImage.parse(resp);
|
||
const ukey = preRespData.upload.uKey;
|
||
if (ukey && ukey != "") {
|
||
this.logger.debug(`[Highway] uploadC2CImageReq get upload ukey: ${ukey}, need upload!`);
|
||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||
const sha1 = Buffer.from(index.info.fileSha1, 'hex');
|
||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||
const extend = new NapProtoMsg(proto.NTV2RichMediaHighwayExt).encode({
|
||
fileUuid: index.fileUuid,
|
||
uKey: ukey,
|
||
network: {
|
||
ipv4S: oidbIpv4s2HighwayIpv4s(preRespData.upload.ipv4S)
|
||
},
|
||
msgInfoBody: preRespData.upload.msgInfo.msgInfoBody,
|
||
blockSize: BlockSize,
|
||
hash: {
|
||
fileSha1: [sha1]
|
||
}
|
||
});
|
||
await this.hwClient.upload(
|
||
1003,
|
||
fs.createReadStream(img.path, { highWaterMark: BlockSize }),
|
||
img.size,
|
||
md5,
|
||
extend
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadC2CImageReq get upload invalid ukey ${ukey}, don't need upload!`);
|
||
}
|
||
img.msgInfo = preRespData.upload.msgInfo;
|
||
}
|
||
|
||
private async uploadGroupVideo(groupUin: number, video: PacketMsgVideoElement): Promise<void> {
|
||
if (!video.filePath || !video.thumbPath) throw new Error("video.filePath or video.thumbPath is empty");
|
||
video.fileSha1 = Buffer.from(await calculateSha1(video.filePath)).toString('hex');
|
||
video.thumbSha1 = Buffer.from(await calculateSha1(video.thumbPath)).toString('hex');
|
||
const req = trans.UploadGroupVideo.build(groupUin, video);
|
||
const resp = await this.context.client.sendOidbPacket(req, true);
|
||
const preRespData = trans.UploadGroupVideo.parse(resp);
|
||
const ukey = preRespData.upload.uKey;
|
||
if (ukey && ukey != "") {
|
||
this.logger.debug(`[Highway] uploadGroupVideoReq get upload video ukey: ${ukey}, need upload!`);
|
||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||
const extend = new NapProtoMsg(proto.NTV2RichMediaHighwayExt).encode({
|
||
fileUuid: index.fileUuid,
|
||
uKey: ukey,
|
||
network: {
|
||
ipv4S: oidbIpv4s2HighwayIpv4s(preRespData.upload.ipv4S)
|
||
},
|
||
msgInfoBody: preRespData.upload.msgInfo.msgInfoBody,
|
||
blockSize: BlockSize,
|
||
hash: {
|
||
fileSha1: await calculateSha1StreamBytes(video.filePath)
|
||
}
|
||
});
|
||
await this.hwClient.upload(
|
||
1005,
|
||
fs.createReadStream(video.filePath, { highWaterMark: BlockSize }),
|
||
+video.fileSize!,
|
||
md5,
|
||
extend
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadGroupVideoReq get upload invalid ukey ${ukey}, don't need upload!`);
|
||
}
|
||
const subFile = preRespData.upload.subFileInfos[0];
|
||
if (subFile.uKey && subFile.uKey != "") {
|
||
this.logger.debug(`[Highway] uploadGroupVideoReq get upload video thumb ukey: ${subFile.uKey}, need upload!`);
|
||
const index = preRespData.upload.msgInfo.msgInfoBody[1].index;
|
||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||
const sha1 = Buffer.from(index.info.fileSha1, 'hex');
|
||
const extend = new NapProtoMsg(proto.NTV2RichMediaHighwayExt).encode({
|
||
fileUuid: index.fileUuid,
|
||
uKey: subFile.uKey,
|
||
network: {
|
||
ipv4S: oidbIpv4s2HighwayIpv4s(subFile.ipv4S)
|
||
},
|
||
msgInfoBody: preRespData.upload.msgInfo.msgInfoBody,
|
||
blockSize: BlockSize,
|
||
hash: {
|
||
fileSha1: [sha1]
|
||
}
|
||
});
|
||
await this.hwClient.upload(
|
||
1006,
|
||
fs.createReadStream(video.thumbPath, { highWaterMark: BlockSize }),
|
||
+video.thumbSize!,
|
||
md5,
|
||
extend
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadGroupVideoReq get upload invalid thumb ukey ${subFile.uKey}, don't need upload!`);
|
||
}
|
||
video.msgInfo = preRespData.upload.msgInfo;
|
||
}
|
||
|
||
private async uploadC2CVideo(peerUid: string, video: PacketMsgVideoElement): Promise<void> {
|
||
if (!video.filePath || !video.thumbPath) throw new Error("video.filePath or video.thumbPath is empty");
|
||
video.fileSha1 = Buffer.from(await calculateSha1(video.filePath)).toString('hex');
|
||
video.thumbSha1 = Buffer.from(await calculateSha1(video.thumbPath)).toString('hex');
|
||
const req = trans.UploadPrivateVideo.build(peerUid, video);
|
||
const resp = await this.context.client.sendOidbPacket(req, true);
|
||
const preRespData = trans.UploadPrivateVideo.parse(resp);
|
||
const ukey = preRespData.upload.uKey;
|
||
if (ukey && ukey != "") {
|
||
this.logger.debug(`[Highway] uploadC2CVideoReq get upload video ukey: ${ukey}, need upload!`);
|
||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||
const extend = new NapProtoMsg(proto.NTV2RichMediaHighwayExt).encode({
|
||
fileUuid: index.fileUuid,
|
||
uKey: ukey,
|
||
network: {
|
||
ipv4S: oidbIpv4s2HighwayIpv4s(preRespData.upload.ipv4S)
|
||
},
|
||
msgInfoBody: preRespData.upload.msgInfo.msgInfoBody,
|
||
blockSize: BlockSize,
|
||
hash: {
|
||
fileSha1: await calculateSha1StreamBytes(video.filePath)
|
||
}
|
||
});
|
||
await this.hwClient.upload(
|
||
1001,
|
||
fs.createReadStream(video.filePath, { highWaterMark: BlockSize }),
|
||
+video.fileSize!,
|
||
md5,
|
||
extend
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadC2CVideoReq get upload invalid ukey ${ukey}, don't need upload!`);
|
||
}
|
||
const subFile = preRespData.upload.subFileInfos[0];
|
||
if (subFile.uKey && subFile.uKey != "") {
|
||
this.logger.debug(`[Highway] uploadC2CVideoReq get upload video thumb ukey: ${subFile.uKey}, need upload!`);
|
||
const index = preRespData.upload.msgInfo.msgInfoBody[1].index;
|
||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||
const sha1 = Buffer.from(index.info.fileSha1, 'hex');
|
||
const extend = new NapProtoMsg(proto.NTV2RichMediaHighwayExt).encode({
|
||
fileUuid: index.fileUuid,
|
||
uKey: subFile.uKey,
|
||
network: {
|
||
ipv4S: oidbIpv4s2HighwayIpv4s(subFile.ipv4S)
|
||
},
|
||
msgInfoBody: preRespData.upload.msgInfo.msgInfoBody,
|
||
blockSize: BlockSize,
|
||
hash: {
|
||
fileSha1: [sha1]
|
||
}
|
||
});
|
||
await this.hwClient.upload(
|
||
1002,
|
||
fs.createReadStream(video.thumbPath, { highWaterMark: BlockSize }),
|
||
+video.thumbSize!,
|
||
md5,
|
||
extend
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadC2CVideoReq get upload invalid thumb ukey ${subFile.uKey}, don't need upload!`);
|
||
}
|
||
video.msgInfo = preRespData.upload.msgInfo;
|
||
}
|
||
|
||
private async uploadGroupPtt(groupUin: number, ptt: PacketMsgPttElement): Promise<void> {
|
||
ptt.fileSha1 = Buffer.from(await calculateSha1(ptt.filePath)).toString('hex');
|
||
const req = trans.UploadGroupPtt.build(groupUin, ptt);
|
||
const resp = await this.context.client.sendOidbPacket(req, true);
|
||
const preRespData = trans.UploadGroupPtt.parse(resp);
|
||
const ukey = preRespData.upload.uKey;
|
||
if (ukey && ukey != "") {
|
||
this.logger.debug(`[Highway] uploadGroupPttReq get upload ptt ukey: ${ukey}, need upload!`);
|
||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||
const sha1 = Buffer.from(index.info.fileSha1, 'hex');
|
||
const extend = new NapProtoMsg(proto.NTV2RichMediaHighwayExt).encode({
|
||
fileUuid: index.fileUuid,
|
||
uKey: ukey,
|
||
network: {
|
||
ipv4S: oidbIpv4s2HighwayIpv4s(preRespData.upload.ipv4S)
|
||
},
|
||
msgInfoBody: preRespData.upload.msgInfo.msgInfoBody,
|
||
blockSize: BlockSize,
|
||
hash: {
|
||
fileSha1: [sha1]
|
||
}
|
||
});
|
||
await this.hwClient.upload(
|
||
1008,
|
||
fs.createReadStream(ptt.filePath, { highWaterMark: BlockSize }),
|
||
ptt.fileSize,
|
||
md5,
|
||
extend
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadGroupPttReq get upload invalid ukey ${ukey}, don't need upload!`);
|
||
}
|
||
ptt.msgInfo = preRespData.upload.msgInfo;
|
||
}
|
||
|
||
private async uploadC2CPtt(peerUid: string, ptt: PacketMsgPttElement): Promise<void> {
|
||
ptt.fileSha1 = Buffer.from(await calculateSha1(ptt.filePath)).toString('hex');
|
||
const req = trans.UploadPrivatePtt.build(peerUid, ptt);
|
||
const resp = await this.context.client.sendOidbPacket(req, true);
|
||
const preRespData = trans.UploadPrivatePtt.parse(resp);
|
||
const ukey = preRespData.upload.uKey;
|
||
if (ukey && ukey != "") {
|
||
this.logger.debug(`[Highway] uploadC2CPttReq get upload ptt ukey: ${ukey}, need upload!`);
|
||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||
const sha1 = Buffer.from(index.info.fileSha1, 'hex');
|
||
const extend = new NapProtoMsg(proto.NTV2RichMediaHighwayExt).encode({
|
||
fileUuid: index.fileUuid,
|
||
uKey: ukey,
|
||
network: {
|
||
ipv4S: oidbIpv4s2HighwayIpv4s(preRespData.upload.ipv4S)
|
||
},
|
||
msgInfoBody: preRespData.upload.msgInfo.msgInfoBody,
|
||
blockSize: BlockSize,
|
||
hash: {
|
||
fileSha1: [sha1]
|
||
}
|
||
});
|
||
await this.hwClient.upload(
|
||
1007,
|
||
fs.createReadStream(ptt.filePath, { highWaterMark: BlockSize }),
|
||
ptt.fileSize,
|
||
md5,
|
||
extend
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadC2CPttReq get upload invalid ukey ${ukey}, don't need upload!`);
|
||
}
|
||
ptt.msgInfo = preRespData.upload.msgInfo;
|
||
}
|
||
|
||
private async uploadGroupFile(groupUin: number, file: PacketMsgFileElement): Promise<void> {
|
||
file.isGroupFile = true;
|
||
file.fileMd5 = await computeMd5AndLengthWithLimit(file.filePath);
|
||
file.fileSha1 = await calculateSha1(file.filePath);
|
||
const req = trans.UploadGroupFile.build(groupUin, file);
|
||
const resp = await this.context.client.sendOidbPacket(req, true);
|
||
const preRespData = trans.UploadGroupFile.parse(resp);
|
||
if (!preRespData?.upload?.boolFileExist) {
|
||
this.logger.debug(`[Highway] uploadGroupFileReq file not exist, need upload!`);
|
||
const ext = new NapProtoMsg(proto.FileUploadExt).encode({
|
||
unknown1: 100,
|
||
unknown2: 1,
|
||
entry: {
|
||
busiBuff: {
|
||
senderUin: BigInt(this.sig.uin),
|
||
receiverUin: BigInt(groupUin),
|
||
groupCode: BigInt(groupUin),
|
||
},
|
||
fileEntry: {
|
||
fileSize: BigInt(file.fileSize),
|
||
md5: file.fileMd5,
|
||
md5S2: file.fileMd5,
|
||
checkKey: preRespData.upload.checkKey,
|
||
fileId: preRespData.upload.fileId,
|
||
uploadKey: preRespData.upload.fileKey,
|
||
},
|
||
clientInfo: {
|
||
clientType: 3,
|
||
appId: "100",
|
||
terminalType: 3,
|
||
clientVer: "1.1.1",
|
||
unknown: 4
|
||
},
|
||
fileNameInfo: {
|
||
fileName: file.fileName
|
||
},
|
||
host: {
|
||
hosts: [
|
||
{
|
||
url: {
|
||
host: preRespData.upload.uploadIp,
|
||
unknown: 1,
|
||
},
|
||
port: preRespData.upload.uploadPort,
|
||
}
|
||
]
|
||
}
|
||
},
|
||
unknown200: 0,
|
||
});
|
||
await this.hwClient.upload(
|
||
71,
|
||
fs.createReadStream(file.filePath, { highWaterMark: BlockSize }),
|
||
file.fileSize,
|
||
file.fileMd5,
|
||
ext
|
||
);
|
||
} else {
|
||
this.logger.debug(`[Highway] uploadGroupFileReq file exist, don't need upload!`);
|
||
}
|
||
file.fileUuid = preRespData.upload.fileId;
|
||
}
|
||
|
||
private async uploadC2CFile(peerUid: string, file: PacketMsgFileElement): Promise<void> {
|
||
file.isGroupFile = false;
|
||
file.fileMd5 = await computeMd5AndLengthWithLimit(file.filePath);
|
||
file.fileSha1 = await calculateSha1(file.filePath);
|
||
const req = await trans.UploadPrivateFile.build(this.sig.uid, peerUid, file);
|
||
const res = await this.context.client.sendOidbPacket(req, true);
|
||
const preRespData = trans.UploadPrivateFile.parse(res);
|
||
if (!preRespData.upload?.boolFileExist) {
|
||
this.logger.debug(`[Highway] uploadC2CFileReq file not exist, need upload!`);
|
||
const ext = new NapProtoMsg(proto.FileUploadExt).encode({
|
||
unknown1: 100,
|
||
unknown2: 1,
|
||
entry: {
|
||
busiBuff: {
|
||
senderUin: BigInt(this.sig.uin),
|
||
},
|
||
fileEntry: {
|
||
fileSize: BigInt(file.fileSize),
|
||
md5: file.fileMd5,
|
||
md5S2: file.fileMd5,
|
||
checkKey: file.fileSha1,
|
||
fileId: preRespData.upload?.uuid,
|
||
uploadKey: preRespData.upload?.mediaPlatformUploadKey,
|
||
},
|
||
clientInfo: {
|
||
clientType: 3,
|
||
appId: "100",
|
||
terminalType: 3,
|
||
clientVer: "1.1.1",
|
||
unknown: 4
|
||
},
|
||
fileNameInfo: {
|
||
fileName: file.fileName
|
||
},
|
||
host: {
|
||
hosts: [
|
||
{
|
||
url: {
|
||
host: preRespData.upload?.uploadIp,
|
||
unknown: 1,
|
||
},
|
||
port: preRespData.upload?.uploadPort,
|
||
}
|
||
]
|
||
}
|
||
},
|
||
unknown200: 1,
|
||
unknown3: 0
|
||
});
|
||
await this.hwClient.upload(
|
||
95,
|
||
fs.createReadStream(file.filePath, { highWaterMark: BlockSize }),
|
||
file.fileSize,
|
||
file.fileMd5,
|
||
ext
|
||
);
|
||
}
|
||
file.fileUuid = preRespData.upload?.uuid;
|
||
file.fileHash = preRespData.upload?.fileAddon;
|
||
const fileExistReq = trans.DownloadOfflineFile.build(file.fileUuid!, file.fileHash!, this.sig.uid, peerUid);
|
||
const fileExistRes = await this.context.client.sendOidbPacket(fileExistReq, true);
|
||
file._e37_800_rsp = trans.DownloadOfflineFile.parse(fileExistRes);
|
||
file._private_send_uid = this.sig.uid;
|
||
file._private_recv_uid = peerUid;
|
||
}
|
||
}
|