mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-21 09:36:35 +00:00
287 lines
11 KiB
TypeScript
287 lines
11 KiB
TypeScript
import * as zlib from "node:zlib";
|
|
import * as crypto from "node:crypto";
|
|
import {calculateSha1} from "@/core/packet/utils/crypto/hash"
|
|
import {NapProtoMsg} from "@/core/packet/proto/NapProto";
|
|
import {OidbSvcTrpcTcpBase} from "@/core/packet/proto/oidb/OidbBase";
|
|
import {OidbSvcTrpcTcp0X9067_202} from "@/core/packet/proto/oidb/Oidb.0x9067_202";
|
|
import {OidbSvcTrpcTcp0X8FC_2, OidbSvcTrpcTcp0X8FC_2_Body} from "@/core/packet/proto/oidb/Oidb.0x8FC_2";
|
|
import {OidbSvcTrpcTcp0XFE1_2} from "@/core/packet/proto/oidb/Oidb.fe1_2";
|
|
import {OidbSvcTrpcTcp0XED3_1} from "@/core/packet/proto/oidb/Oidb.ed3_1";
|
|
import {NTV2RichMediaReq} from "@/core/packet/proto/oidb/common/Ntv2.RichMediaReq";
|
|
import {HttpConn0x6ff_501} from "@/core/packet/proto/action/action";
|
|
import {LongMsgResult, SendLongMsgReq} from "@/core/packet/proto/message/action";
|
|
import {PacketMsgBuilder} from "@/core/packet/msg/builder";
|
|
import {PacketMsgPicElement} from "@/core/packet/msg/element";
|
|
import {LogWrapper} from "@/common/log";
|
|
import {PacketMsg} from "@/core/packet/msg/message";
|
|
|
|
export type PacketHexStr = string & { readonly hexNya: unique symbol };
|
|
|
|
export class PacketPacker {
|
|
private readonly logger: LogWrapper;
|
|
private readonly packetBuilder: PacketMsgBuilder;
|
|
|
|
constructor(logger: LogWrapper) {
|
|
this.logger = logger;
|
|
this.packetBuilder = new PacketMsgBuilder(logger);
|
|
}
|
|
|
|
private toHexStr(byteArray: Uint8Array): PacketHexStr {
|
|
return Buffer.from(byteArray).toString('hex') as PacketHexStr;
|
|
}
|
|
|
|
packOidbPacket(cmd: number, subCmd: number, body: Uint8Array, isUid: boolean = true, isLafter: boolean = false): Uint8Array {
|
|
return new NapProtoMsg(OidbSvcTrpcTcpBase).encode({
|
|
command: cmd,
|
|
subCommand: subCmd,
|
|
body: body,
|
|
isReserved: isUid ? 1 : 0
|
|
});
|
|
}
|
|
|
|
packPokePacket(group: number, peer: number): PacketHexStr {
|
|
const oidb_0xed3 = new NapProtoMsg(OidbSvcTrpcTcp0XED3_1).encode({
|
|
uin: peer,
|
|
groupUin: group,
|
|
friendUin: group,
|
|
ext: 0
|
|
});
|
|
return this.toHexStr(this.packOidbPacket(0xed3, 1, oidb_0xed3));
|
|
}
|
|
|
|
packRkeyPacket(): PacketHexStr {
|
|
const oidb_0x9067_202 = new NapProtoMsg(OidbSvcTrpcTcp0X9067_202).encode({
|
|
reqHead: {
|
|
common: {
|
|
requestId: 1,
|
|
command: 202
|
|
},
|
|
scene: {
|
|
requestType: 2,
|
|
businessType: 1,
|
|
sceneType: 0
|
|
},
|
|
client: {
|
|
agentType: 2
|
|
}
|
|
},
|
|
downloadRKeyReq: {
|
|
key: [10, 20, 2]
|
|
},
|
|
});
|
|
return this.toHexStr(this.packOidbPacket(0x9067, 202, oidb_0x9067_202));
|
|
}
|
|
|
|
packSetSpecialTittlePacket(groupCode: string, uid: string, tittle: string): PacketHexStr {
|
|
const oidb_0x8FC_2_body = new NapProtoMsg(OidbSvcTrpcTcp0X8FC_2_Body).encode({
|
|
targetUid: uid,
|
|
specialTitle: tittle,
|
|
expiredTime: -1,
|
|
uinName: tittle
|
|
});
|
|
const oidb_0x8FC_2 = new NapProtoMsg(OidbSvcTrpcTcp0X8FC_2).encode({
|
|
groupUin: +groupCode,
|
|
body: oidb_0x8FC_2_body
|
|
});
|
|
return this.toHexStr(this.packOidbPacket(0x8FC, 2, oidb_0x8FC_2, false, false));
|
|
}
|
|
|
|
packStatusPacket(uin: number): PacketHexStr {
|
|
const oidb_0xfe1_2 = new NapProtoMsg(OidbSvcTrpcTcp0XFE1_2).encode({
|
|
uin: uin,
|
|
key: [{key: 27372}]
|
|
});
|
|
return this.toHexStr(this.packOidbPacket(0xfe1, 2, oidb_0xfe1_2));
|
|
}
|
|
|
|
packUploadForwardMsg(selfUid: string, msg: PacketMsg[], groupUin: number = 0): PacketHexStr {
|
|
// this.logger.logDebug("packUploadForwardMsg START!!!", selfUid, msg, groupUin);
|
|
const msgBody = this.packetBuilder.buildFakeMsg(selfUid, msg);
|
|
const longMsgResultData = new NapProtoMsg(LongMsgResult).encode(
|
|
{
|
|
action: {
|
|
actionCommand: "MultiMsg",
|
|
actionData: {
|
|
msgBody: msgBody
|
|
}
|
|
}
|
|
}
|
|
);
|
|
this.logger.logDebug("packUploadForwardMsg LONGMSGRESULT!!!", this.toHexStr(longMsgResultData));
|
|
const payload = zlib.gzipSync(Buffer.from(longMsgResultData));
|
|
// this.logger.logDebug("packUploadForwardMsg PAYLOAD!!!", payload);
|
|
const req = new NapProtoMsg(SendLongMsgReq).encode(
|
|
{
|
|
info: {
|
|
type: groupUin === 0 ? 1 : 3,
|
|
uid: {
|
|
uid: groupUin === 0 ? selfUid : groupUin.toString(),
|
|
},
|
|
groupUin: groupUin,
|
|
payload: payload
|
|
},
|
|
settings: {
|
|
field1: 4, field2: 1, field3: 7, field4: 0
|
|
}
|
|
}
|
|
);
|
|
// this.logger.logDebug("packUploadForwardMsg REQ!!!", req);
|
|
return this.toHexStr(req);
|
|
}
|
|
|
|
// highway part
|
|
packHttp0x6ff_501() {
|
|
return this.toHexStr(new NapProtoMsg(HttpConn0x6ff_501).encode({
|
|
httpConn: {
|
|
field1: 0,
|
|
field2: 0,
|
|
field3: 16,
|
|
field4: 1,
|
|
field6: 3,
|
|
serviceTypes: [1, 5, 10, 21],
|
|
// tgt: "", // TODO: do we really need tgt? seems not
|
|
field9: 2,
|
|
field10: 9,
|
|
field11: 8,
|
|
ver: "1.0.1"
|
|
}
|
|
}));
|
|
}
|
|
|
|
async packUploadGroupImgReq(groupUin: number, img: PacketMsgPicElement) {
|
|
const req = new NapProtoMsg(NTV2RichMediaReq).encode(
|
|
{
|
|
reqHead: {
|
|
common: {
|
|
requestId: 1,
|
|
command: 100
|
|
},
|
|
scene: {
|
|
requestType: 2,
|
|
businessType: 1,
|
|
sceneType: 2,
|
|
group: {
|
|
groupUin: groupUin
|
|
},
|
|
},
|
|
client: {
|
|
agentType: 2
|
|
}
|
|
},
|
|
upload: {
|
|
uploadInfo: [
|
|
{
|
|
fileInfo: {
|
|
fileSize: Number(img.size),
|
|
fileHash: img.md5,
|
|
fileSha1: this.toHexStr(await calculateSha1(img.path)),
|
|
fileName: img.name,
|
|
type: {
|
|
type: 1,
|
|
picFormat: img.picType, //TODO: extend NapCat imgType /cc @MliKiowa
|
|
videoFormat: 0,
|
|
voiceFormat: 0,
|
|
},
|
|
width: img.width,
|
|
height: img.height,
|
|
time: 0,
|
|
original: 1
|
|
},
|
|
subFileType: 0,
|
|
}
|
|
],
|
|
tryFastUploadCompleted: true,
|
|
srvSendMsg: false,
|
|
clientRandomId: crypto.randomBytes(8).readBigUInt64BE() & BigInt('0x7FFFFFFFFFFFFFFF'),
|
|
compatQMsgSceneType: 2,
|
|
extBizInfo: {
|
|
pic: {
|
|
bytesPbReserveTroop: Buffer.from("0800180020004200500062009201009a0100a2010c080012001800200028003a00", 'hex'),
|
|
textSummary: "Nya~", // TODO:
|
|
},
|
|
video: {
|
|
bytesPbReserve: Buffer.alloc(0),
|
|
},
|
|
ptt: {
|
|
bytesPbReserve: Buffer.alloc(0),
|
|
bytesReserve: Buffer.alloc(0),
|
|
bytesGeneralFlags: Buffer.alloc(0),
|
|
}
|
|
},
|
|
clientSeq: 0,
|
|
noNeedCompatMsg: false,
|
|
}
|
|
}
|
|
)
|
|
return this.toHexStr(this.packOidbPacket(0x11c4, 100, req, true, false));
|
|
}
|
|
|
|
async packUploadC2CImgReq(peerUin: string, img: PacketMsgPicElement) {
|
|
const req = new NapProtoMsg(NTV2RichMediaReq).encode({
|
|
reqHead: {
|
|
common: {
|
|
requestId: 1,
|
|
command: 100
|
|
},
|
|
scene: {
|
|
requestType: 2,
|
|
businessType: 1,
|
|
sceneType: 1,
|
|
c2C: {
|
|
accountType: 2,
|
|
targetUid: peerUin
|
|
},
|
|
},
|
|
client: {
|
|
agentType: 2,
|
|
}
|
|
},
|
|
upload: {
|
|
uploadInfo: [
|
|
{
|
|
fileInfo: {
|
|
fileSize: Number(img.size),
|
|
fileHash: img.md5,
|
|
fileSha1: this.toHexStr(await calculateSha1(img.path)),
|
|
fileName: img.name,
|
|
type: {
|
|
type: 1,
|
|
picFormat: img.picType, //TODO: extend NapCat imgType /cc @MliKiowa
|
|
videoFormat: 0,
|
|
voiceFormat: 0,
|
|
},
|
|
width: img.width,
|
|
height: img.height,
|
|
time: 0,
|
|
original: 1
|
|
},
|
|
subFileType: 0,
|
|
}
|
|
],
|
|
tryFastUploadCompleted: true,
|
|
srvSendMsg: false,
|
|
clientRandomId: crypto.randomBytes(8).readBigUInt64BE() & BigInt('0x7FFFFFFFFFFFFFFF'),
|
|
compatQMsgSceneType: 1,
|
|
extBizInfo: {
|
|
pic: {
|
|
bytesPbReserveTroop: Buffer.from("0800180020004200500062009201009a0100a2010c080012001800200028003a00", 'hex'),
|
|
textSummary: "Nya~", // TODO:
|
|
},
|
|
video: {
|
|
bytesPbReserve: Buffer.alloc(0),
|
|
},
|
|
ptt: {
|
|
bytesPbReserve: Buffer.alloc(0),
|
|
bytesReserve: Buffer.alloc(0),
|
|
bytesGeneralFlags: Buffer.alloc(0),
|
|
}
|
|
},
|
|
clientSeq: 0,
|
|
noNeedCompatMsg: false,
|
|
}
|
|
}
|
|
)
|
|
return this.toHexStr(this.packOidbPacket(0x11c5, 100, req, true, false));
|
|
}
|
|
}
|