mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-03-02 08:40:26 +00:00
feat: build & upload file
This commit is contained in:
@@ -8,10 +8,17 @@ import { HttpConn0x6ff_501Response } from "@/core/packet/proto/action/action";
|
||||
import { PacketHighwayClient } from "@/core/packet/highway/client";
|
||||
import { NTV2RichMediaResp } from "@/core/packet/proto/oidb/common/Ntv2.RichMediaResp";
|
||||
import { OidbSvcTrpcTcpBaseRsp } from "@/core/packet/proto/oidb/OidbBase";
|
||||
import { PacketMsgPicElement, PacketMsgPttElement, PacketMsgVideoElement } from "@/core/packet/msg/element";
|
||||
import { NTV2RichMediaHighwayExt } from "@/core/packet/proto/highway/highway";
|
||||
import {
|
||||
PacketMsgFileElement,
|
||||
PacketMsgPicElement,
|
||||
PacketMsgPttElement,
|
||||
PacketMsgVideoElement
|
||||
} from "@/core/packet/msg/element";
|
||||
import { FileUploadExt, NTV2RichMediaHighwayExt } from "@/core/packet/proto/highway/highway";
|
||||
import { int32ip2str, oidbIpv4s2HighwayIpv4s } from "@/core/packet/highway/utils";
|
||||
import { calculateSha1StreamBytes } from "@/core/packet/utils/crypto/hash";
|
||||
import { calculateSha1, calculateSha1StreamBytes, computeMd5AndLengthWithLimit } from "@/core/packet/utils/crypto/hash";
|
||||
import { OidbSvcTrpcTcp0x6D6Response } from "@/core/packet/proto/oidb/Oidb.0x6D6";
|
||||
import { OidbSvcTrpcTcp0XE37_800Response, OidbSvcTrpcTcp0XE37Response } from "@/core/packet/proto/oidb/Oidb.0XE37_800";
|
||||
|
||||
export const BlockSize = 1024 * 1024;
|
||||
|
||||
@@ -22,6 +29,7 @@ interface HighwayServerAddr {
|
||||
|
||||
export interface PacketHighwaySig {
|
||||
uin: string;
|
||||
uid: string;
|
||||
sigSession: Uint8Array | null
|
||||
sessionKey: Uint8Array | null
|
||||
serverAddr: HighwayServerAddr[]
|
||||
@@ -40,6 +48,7 @@ export class PacketHighwaySession {
|
||||
this.logger = logger;
|
||||
this.sig = {
|
||||
uin: this.packetClient.napCatCore.selfInfo.uin,
|
||||
uid: this.packetClient.napCatCore.selfInfo.uid,
|
||||
sigSession: null,
|
||||
sessionKey: null,
|
||||
serverAddr: [],
|
||||
@@ -117,6 +126,17 @@ export class PacketHighwaySession {
|
||||
}
|
||||
}
|
||||
|
||||
async uploadFile(peer: Peer, file: PacketMsgFileElement): Promise<void> {
|
||||
await this.checkAvailable();
|
||||
if (peer.chatType === ChatType.KCHATTYPEGROUP) {
|
||||
await this.uploadGroupFileReq(Number(peer.peerUid), file);
|
||||
} else if (peer.chatType === ChatType.KCHATTYPEC2C) {
|
||||
await this.uploadC2CFileReq(peer.peerUid, file);
|
||||
} else {
|
||||
throw new Error(`[Highway] unsupported chatType: ${peer.chatType}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async uploadGroupImageReq(groupUin: number, img: PacketMsgPicElement): Promise<void> {
|
||||
const preReq = await this.packer.packUploadGroupImgReq(groupUin, img);
|
||||
const preRespRaw = await this.packetClient.sendPacket('OidbSvcTrpcTcp.0x11c4_100', preReq, true);
|
||||
@@ -400,4 +420,142 @@ export class PacketHighwaySession {
|
||||
}
|
||||
ptt.msgInfo = preRespData.upload.msgInfo;
|
||||
}
|
||||
|
||||
private async uploadGroupFileReq(groupUin: number, file: PacketMsgFileElement): Promise<void> {
|
||||
file.isGroupFile = true;
|
||||
file.fileMd5 = await computeMd5AndLengthWithLimit(file.filePath);
|
||||
file.fileSha1 = await calculateSha1(file.filePath);
|
||||
const preReq = await this.packer.packUploadGroupFileReq(groupUin, file);
|
||||
const preRespRaw = await this.packetClient.sendPacket('OidbSvcTrpcTcp.0x6d6_0', preReq, true);
|
||||
const preResp = new NapProtoMsg(OidbSvcTrpcTcpBaseRsp).decode(
|
||||
Buffer.from(preRespRaw.hex_data, 'hex')
|
||||
);
|
||||
const preRespData = new NapProtoMsg(OidbSvcTrpcTcp0x6D6Response).decode(preResp.body);
|
||||
if (!preRespData?.upload?.boolFileExist) {
|
||||
this.logger.logDebug(`[Highway] uploadGroupFileReq file not exist, need upload!`);
|
||||
const ext = new NapProtoMsg(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.packetHighwayClient.upload(
|
||||
71,
|
||||
fs.createReadStream(file.filePath, {highWaterMark: BlockSize}),
|
||||
file.fileSize,
|
||||
file.fileMd5,
|
||||
ext
|
||||
);
|
||||
} else {
|
||||
this.logger.logDebug(`[Highway] uploadGroupFileReq file exist, don't need upload!`);
|
||||
}
|
||||
file.fileUuid = preRespData.upload.fileId;
|
||||
}
|
||||
|
||||
private async uploadC2CFileReq(peerUid: string, file: PacketMsgFileElement): Promise<void> {
|
||||
file.isGroupFile = false;
|
||||
file.fileMd5 = await computeMd5AndLengthWithLimit(file.filePath);
|
||||
file.fileSha1 = await calculateSha1(file.filePath);
|
||||
const preReq = await this.packer.packUploadC2CFileReq(this.sig.uid, peerUid, file);
|
||||
const preRespRaw = await this.packetClient.sendPacket('OidbSvcTrpcTcp.0xe37_1700', preReq, true);
|
||||
const preResp = new NapProtoMsg(OidbSvcTrpcTcpBaseRsp).decode(
|
||||
Buffer.from(preRespRaw.hex_data, 'hex')
|
||||
);
|
||||
console.log("OidbSvcTrpcTcp.0xe37_1700", preRespRaw);
|
||||
const preRespData = new NapProtoMsg(OidbSvcTrpcTcp0XE37Response).decode(preResp.body);
|
||||
if (!preRespData.upload?.boolFileExist) {
|
||||
this.logger.logDebug(`[Highway] uploadC2CFileReq file not exist, need upload!`);
|
||||
const ext = new NapProtoMsg(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.packetHighwayClient.upload(
|
||||
95,
|
||||
fs.createReadStream(file.filePath, {highWaterMark: BlockSize}),
|
||||
file.fileSize,
|
||||
file.fileMd5,
|
||||
ext
|
||||
);
|
||||
}
|
||||
file.fileUuid = preRespData.upload?.uuid;
|
||||
file.fileHash = preRespData.upload?.fileAddon;
|
||||
const FetchExistFileReq = this.packer.packOfflineFileDownloadReq(file.fileUuid!, file.fileHash!, this.sig.uid, peerUid);
|
||||
const resp = await this.packetClient.sendPacket('OidbSvcTrpcTcp.0xe37_800', FetchExistFileReq, true);
|
||||
console.log("OidbSvcTrpcTcp.0xe37_800", resp);
|
||||
const oidb_resp = new NapProtoMsg(OidbSvcTrpcTcpBaseRsp).decode(Buffer.from(resp.hex_data, 'hex'));
|
||||
file._e37_800_rsp = new NapProtoMsg(OidbSvcTrpcTcp0XE37_800Response).decode(oidb_resp.body);
|
||||
file._private_send_uid = this.sig.uid;
|
||||
file._private_recv_uid = peerUid;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user