SnowCat 雪猫底层全源码:NapCat 4.18.28 底座 + SnowLuma 能力移植 + V8 通道适配 9.9.37
26 包 monorepo(TS 全源码): - snowcat-core: NT 内核 API 封装 + listener(含 9.9.37 六回调适配)+ Packet 发包 - snowcat-onebot: OneBot v11 全动作 + MCP Streamable HTTP 适配器 + 稳定线 - snowcat-webui-frontend/backend: 雪猫控制台(React+HeroUI) - snowcat-shell: 单文件 bundle 出口(vite inlineDynamicImports) - snowcat-native: napi2native / MoeHoo / ffmpeg / pty 运行时 - 56 项 SnowLuma 独门动作移植(qzone 全家桶/群相册/装扮/闪照/收藏) - 工具件: 解包器/启动器/便携制作器/doctor GitHub 关联已全量指向 DandanLLab/SnowCatQQ
This commit is contained in:
commit
b9655a5ab1
1048 files changed
+130851
No files matched your search
@@ -0,0 +1,29 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class DownloadGroupFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0x6D6Response> {
|
||||
build (groupUin: number, fileUUID: string): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.OidbSvcTrpcTcp0x6D6).encode({
|
||||
download: {
|
||||
groupUin,
|
||||
appId: 7,
|
||||
busId: 102,
|
||||
fileId: fileUUID,
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x6D6, 2, body, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
const res = new NapProtoMsg(proto.OidbSvcTrpcTcp0x6D6Response).decode(oidbBody);
|
||||
if (res.download.retCode !== 0) {
|
||||
throw new Error(`sendGroupFileDownloadReq error: ${res.download.clientWording} (code=${res.download.retCode})`);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadGroupFile();
|
||||
@@ -0,0 +1,46 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import { IndexNode } from '@/snowcat-core/packet/transformer/proto';
|
||||
|
||||
class DownloadGroupImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (group_uin: number, node: NapProtoEncodeStructType<typeof IndexNode>): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 1,
|
||||
command: 200,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 1,
|
||||
sceneType: 2,
|
||||
group: {
|
||||
groupUin: group_uin,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
download: {
|
||||
node,
|
||||
download: {
|
||||
video: {
|
||||
busiType: 0,
|
||||
sceneType: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x11C4, 200, body, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadGroupImage();
|
||||
@@ -0,0 +1,45 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class DownloadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (groupUin: number, node: NapProtoEncodeStructType<typeof proto.IndexNode>): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 4,
|
||||
command: 200,
|
||||
},
|
||||
scene: {
|
||||
requestType: 1,
|
||||
businessType: 3,
|
||||
sceneType: 2,
|
||||
group: {
|
||||
groupUin,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
download: {
|
||||
node,
|
||||
download: {
|
||||
video: {
|
||||
busiType: 0,
|
||||
sceneType: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x126E, 200, body, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadGroupPtt();
|
||||
@@ -0,0 +1,46 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import { IndexNode } from '@/snowcat-core/packet/transformer/proto';
|
||||
|
||||
class DownloadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (groupUin: number, node: NapProtoEncodeStructType<typeof IndexNode>): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 1,
|
||||
command: 200,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 2,
|
||||
sceneType: 2,
|
||||
group: {
|
||||
groupUin,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
download: {
|
||||
node,
|
||||
download: {
|
||||
video: {
|
||||
busiType: 0,
|
||||
sceneType: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x11EA, 200, body, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadGroupVideo();
|
||||
@@ -0,0 +1,47 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import { IndexNode } from '@/snowcat-core/packet/transformer/proto';
|
||||
|
||||
class DownloadImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (selfUid: string, node: NapProtoEncodeStructType<typeof IndexNode>): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 1,
|
||||
command: 200,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 1,
|
||||
sceneType: 1,
|
||||
c2C: {
|
||||
accountType: 2,
|
||||
targetUid: selfUid,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
download: {
|
||||
node,
|
||||
download: {
|
||||
video: {
|
||||
busiType: 0,
|
||||
sceneType: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x11C5, 200, body, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadImage();
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class DownloadOfflineFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37Response> {
|
||||
build (fileUUID: string, fileHash: string, senderUid: string, receiverUid: string): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.OidbSvcTrpcTcp0XE37_800).encode({
|
||||
subCommand: 800,
|
||||
field2: 0,
|
||||
body: {
|
||||
senderUid,
|
||||
receiverUid,
|
||||
fileUuid: fileUUID,
|
||||
fileHash,
|
||||
},
|
||||
field101: 3,
|
||||
field102: 1,
|
||||
field200: 1,
|
||||
});
|
||||
return OidbBase.build(0xE37, 800, body, false, false);
|
||||
}
|
||||
|
||||
// TODO:check
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.OidbSvcTrpcTcp0XE37Response).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadOfflineFile();
|
||||
@@ -0,0 +1,32 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class DownloadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37_1200Response> {
|
||||
build (selfUid: string, fileUUID: string, fileHash: string): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.OidbSvcTrpcTcp0XE37_1200).encode({
|
||||
subCommand: 1200,
|
||||
field2: 1,
|
||||
body: {
|
||||
receiverUid: selfUid,
|
||||
fileUuid: fileUUID,
|
||||
type: 2,
|
||||
fileHash,
|
||||
t2: 0,
|
||||
},
|
||||
field101: 3,
|
||||
field102: 103,
|
||||
field200: 1,
|
||||
field99999: Buffer.from([0xc0, 0x85, 0x2c, 0x01]),
|
||||
});
|
||||
return OidbBase.build(0xE37, 1200, body, false, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.OidbSvcTrpcTcp0XE37_1200Response).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadPrivateFile();
|
||||
@@ -0,0 +1,47 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import { IndexNode } from '@/snowcat-core/packet/transformer/proto';
|
||||
|
||||
class DownloadPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (selfUid: string, node: NapProtoEncodeStructType<typeof IndexNode>): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 1,
|
||||
command: 200,
|
||||
},
|
||||
scene: {
|
||||
requestType: 1,
|
||||
businessType: 3,
|
||||
sceneType: 1,
|
||||
c2C: {
|
||||
accountType: 2,
|
||||
targetUid: selfUid,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
download: {
|
||||
node,
|
||||
download: {
|
||||
video: {
|
||||
busiType: 0,
|
||||
sceneType: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x126D, 200, body, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadPtt();
|
||||
@@ -0,0 +1,47 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import { IndexNode } from '@/snowcat-core/packet/transformer/proto';
|
||||
|
||||
class DownloadVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (selfUid: string, node: NapProtoEncodeStructType<typeof IndexNode>): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 1,
|
||||
command: 200,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 2,
|
||||
sceneType: 1,
|
||||
c2C: {
|
||||
accountType: 2,
|
||||
targetUid: selfUid,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
download: {
|
||||
node,
|
||||
download: {
|
||||
video: {
|
||||
busiType: 0,
|
||||
sceneType: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x11E9, 200, body, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DownloadVideo();
|
||||
@@ -0,0 +1,33 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketBufBuilder, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
|
||||
class FetchSessionKey extends PacketTransformer<typeof proto.HttpConn0x6ff_501Response> {
|
||||
build (): OidbPacket {
|
||||
const req = new NapProtoMsg(proto.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',
|
||||
},
|
||||
});
|
||||
return {
|
||||
cmd: 'HttpConn.0x6ff_501',
|
||||
data: PacketBufBuilder(req),
|
||||
};
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
return new NapProtoMsg(proto.HttpConn0x6ff_501Response).decode(data);
|
||||
}
|
||||
}
|
||||
|
||||
export default new FetchSessionKey();
|
||||
@@ -0,0 +1,34 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import { PacketMsgFileElement } from '@/snowcat-core/packet/message/element';
|
||||
|
||||
class UploadGroupFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0x6D6Response> {
|
||||
build (groupUin: number, file: PacketMsgFileElement): OidbPacket {
|
||||
const body = new NapProtoMsg(proto.OidbSvcTrpcTcp0x6D6).encode({
|
||||
file: {
|
||||
groupUin,
|
||||
appId: 4,
|
||||
busId: 102,
|
||||
entrance: 6,
|
||||
targetDirectory: '/', // TODO:
|
||||
fileName: file.fileName,
|
||||
localDirectory: `/${file.fileName}`,
|
||||
fileSize: BigInt(file.fileSize),
|
||||
fileMd5: file.fileMd5,
|
||||
fileSha1: file.fileSha1,
|
||||
fileSha3: Buffer.alloc(0),
|
||||
field15: true,
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x6D6, 0, body, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.OidbSvcTrpcTcp0x6D6Response).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new UploadGroupFile();
|
||||
@@ -0,0 +1,86 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgPicElement } from '@/snowcat-core/packet/message/element';
|
||||
|
||||
class UploadGroupImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (groupUin: number, img: PacketMsgPicElement): OidbPacket {
|
||||
const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode(
|
||||
{
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 1,
|
||||
command: 100,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 1,
|
||||
sceneType: 2,
|
||||
group: {
|
||||
groupUin,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
upload: {
|
||||
uploadInfo: [
|
||||
{
|
||||
fileInfo: {
|
||||
fileSize: +img.size,
|
||||
fileHash: img.md5,
|
||||
fileSha1: img.sha1!,
|
||||
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: {
|
||||
bizType: img.picSubType,
|
||||
bytesPbReserveTroop: {
|
||||
subType: img.picSubType,
|
||||
},
|
||||
textSummary: img.summary,
|
||||
},
|
||||
video: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
},
|
||||
ptt: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
bytesReserve: Buffer.alloc(0),
|
||||
bytesGeneralFlags: Buffer.alloc(0),
|
||||
},
|
||||
},
|
||||
clientSeq: 0,
|
||||
noNeedCompatMsg: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
return OidbBase.build(0x11C4, 100, data, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new UploadGroupImage();
|
||||
@@ -0,0 +1,82 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgPttElement } from '@/snowcat-core/packet/message/element';
|
||||
|
||||
class UploadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (groupUin: number, ptt: PacketMsgPttElement): OidbPacket {
|
||||
const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 1,
|
||||
command: 100,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 3,
|
||||
sceneType: 2,
|
||||
group: {
|
||||
groupUin,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
upload: {
|
||||
uploadInfo: [
|
||||
{
|
||||
fileInfo: {
|
||||
fileSize: ptt.fileSize,
|
||||
fileHash: ptt.fileMd5,
|
||||
fileSha1: ptt.fileSha1,
|
||||
fileName: `${ptt.fileMd5}.amr`,
|
||||
type: {
|
||||
type: 3,
|
||||
picFormat: 0,
|
||||
videoFormat: 0,
|
||||
voiceFormat: 1,
|
||||
},
|
||||
height: 0,
|
||||
width: 0,
|
||||
time: ptt.fileDuration,
|
||||
original: 0,
|
||||
},
|
||||
subFileType: 0,
|
||||
},
|
||||
],
|
||||
tryFastUploadCompleted: true,
|
||||
srvSendMsg: false,
|
||||
clientRandomId: crypto.randomBytes(8).readBigUInt64BE() & BigInt('0x7FFFFFFFFFFFFFFF'),
|
||||
compatQMsgSceneType: 2,
|
||||
extBizInfo: {
|
||||
pic: {
|
||||
textSummary: 'Nya~',
|
||||
},
|
||||
video: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
},
|
||||
ptt: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
bytesReserve: Buffer.from([0x08, 0x00, 0x38, 0x00]),
|
||||
bytesGeneralFlags: Buffer.from([0x9a, 0x01, 0x07, 0xaa, 0x03, 0x04, 0x08, 0x08, 0x12, 0x00]),
|
||||
},
|
||||
},
|
||||
clientSeq: 0,
|
||||
noNeedCompatMsg: false,
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x126E, 100, data, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
const instance = new UploadGroupPtt();
|
||||
|
||||
export default instance;
|
||||
@@ -0,0 +1,100 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgVideoElement } from '@/snowcat-core/packet/message/element';
|
||||
|
||||
class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (groupUin: number, video: PacketMsgVideoElement): OidbPacket {
|
||||
if (!video.fileSize || !video.thumbSize) throw new Error('video.fileSize or video.thumbSize is empty');
|
||||
const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 3,
|
||||
command: 100,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 2,
|
||||
sceneType: 2,
|
||||
group: {
|
||||
groupUin,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
upload: {
|
||||
uploadInfo: [
|
||||
{
|
||||
fileInfo: {
|
||||
fileSize: +video.fileSize,
|
||||
fileHash: video.fileMd5,
|
||||
fileSha1: video.fileSha1,
|
||||
fileName: video.fileName || 'video.mp4',
|
||||
type: {
|
||||
type: 2,
|
||||
picFormat: 0,
|
||||
videoFormat: video.fileFormat,
|
||||
voiceFormat: 0,
|
||||
},
|
||||
height: video.fileHeight ?? 0,
|
||||
width: video.fileWidth ?? 0,
|
||||
time: video.fileTime,
|
||||
original: 0,
|
||||
},
|
||||
subFileType: 0,
|
||||
}, {
|
||||
fileInfo: {
|
||||
fileSize: +video.thumbSize,
|
||||
fileHash: video.thumbMd5,
|
||||
fileSha1: video.thumbSha1,
|
||||
fileName: `${video.thumbMd5 || 'video-thumb'}.jpg`,
|
||||
type: {
|
||||
type: 1,
|
||||
picFormat: 0,
|
||||
videoFormat: 0,
|
||||
voiceFormat: 0,
|
||||
},
|
||||
height: video.thumbHeight,
|
||||
width: video.thumbWidth,
|
||||
time: 0,
|
||||
original: 0,
|
||||
},
|
||||
subFileType: 100,
|
||||
},
|
||||
],
|
||||
tryFastUploadCompleted: true,
|
||||
srvSendMsg: false,
|
||||
clientRandomId: crypto.randomBytes(8).readBigUInt64BE() & BigInt('0x7FFFFFFFFFFFFFFF'),
|
||||
compatQMsgSceneType: 2,
|
||||
extBizInfo: {
|
||||
pic: {
|
||||
bizType: 0,
|
||||
textSummary: 'Nya~',
|
||||
},
|
||||
video: {
|
||||
bytesPbReserve: Buffer.from([0x80, 0x01, 0x00]),
|
||||
},
|
||||
ptt: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
bytesReserve: Buffer.alloc(0),
|
||||
bytesGeneralFlags: Buffer.alloc(0),
|
||||
},
|
||||
},
|
||||
clientSeq: 0,
|
||||
noNeedCompatMsg: false,
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x11EA, 100, data, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new UploadGroupVideo();
|
||||
@@ -0,0 +1,37 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import { PacketMsgFileElement } from '@/snowcat-core/packet/message/element';
|
||||
import { computeMd5AndLengthWithLimit } from '@/snowcat-core/packet/utils/crypto/hash';
|
||||
|
||||
class UploadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37Response> {
|
||||
async build (selfUid: string, peerUid: string, file: PacketMsgFileElement): Promise<OidbPacket> {
|
||||
const body = new NapProtoMsg(proto.OidbSvcTrpcTcp0XE37_1700).encode({
|
||||
command: 1700,
|
||||
seq: 0,
|
||||
upload: {
|
||||
senderUid: selfUid,
|
||||
receiverUid: peerUid,
|
||||
fileSize: file.fileSize,
|
||||
fileName: file.fileName,
|
||||
md510MCheckSum: await computeMd5AndLengthWithLimit(file.filePath, 10 * 1024 * 1024),
|
||||
sha1CheckSum: file.fileSha1,
|
||||
localPath: '/',
|
||||
md5CheckSum: file.fileMd5,
|
||||
sha3CheckSum: Buffer.alloc(0),
|
||||
},
|
||||
businessId: 3,
|
||||
clientType: 1,
|
||||
flagSupportMediaPlatform: 1,
|
||||
});
|
||||
return OidbBase.build(0xE37, 1700, body, false, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.OidbSvcTrpcTcp0XE37Response).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new UploadPrivateFile();
|
||||
@@ -0,0 +1,86 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgPicElement } from '@/snowcat-core/packet/message/element';
|
||||
|
||||
class UploadPrivateImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (peerUin: string, img: PacketMsgPicElement): OidbPacket {
|
||||
const data = new NapProtoMsg(proto.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: +img.size,
|
||||
fileHash: img.md5,
|
||||
fileSha1: img.sha1!,
|
||||
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: {
|
||||
bizType: img.picSubType,
|
||||
bytesPbReserveC2C: {
|
||||
subType: img.picSubType,
|
||||
},
|
||||
textSummary: img.summary,
|
||||
},
|
||||
video: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
},
|
||||
ptt: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
bytesReserve: Buffer.alloc(0),
|
||||
bytesGeneralFlags: Buffer.alloc(0),
|
||||
},
|
||||
},
|
||||
clientSeq: 0,
|
||||
noNeedCompatMsg: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
return OidbBase.build(0x11C5, 100, data, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new UploadPrivateImage();
|
||||
@@ -0,0 +1,77 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgPttElement } from '@/snowcat-core/packet/message/element';
|
||||
|
||||
class UploadPrivatePtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (peerUin: string, ptt: PacketMsgPttElement): OidbPacket {
|
||||
const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 4,
|
||||
command: 100,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 3,
|
||||
sceneType: 1,
|
||||
c2C: {
|
||||
accountType: 2,
|
||||
targetUid: peerUin,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
upload: {
|
||||
uploadInfo: [
|
||||
{
|
||||
fileInfo: {
|
||||
fileSize: ptt.fileSize,
|
||||
fileHash: ptt.fileMd5,
|
||||
fileSha1: ptt.fileSha1,
|
||||
fileName: `${ptt.fileMd5}.amr`,
|
||||
type: {
|
||||
type: 3,
|
||||
picFormat: 0,
|
||||
videoFormat: 0,
|
||||
voiceFormat: 1,
|
||||
},
|
||||
height: 0,
|
||||
width: 0,
|
||||
time: ptt.fileDuration,
|
||||
original: 0,
|
||||
},
|
||||
subFileType: 0,
|
||||
},
|
||||
],
|
||||
tryFastUploadCompleted: true,
|
||||
srvSendMsg: false,
|
||||
clientRandomId: crypto.randomBytes(8).readBigUInt64BE() & BigInt('0x7FFFFFFFFFFFFFFF'),
|
||||
compatQMsgSceneType: 1,
|
||||
extBizInfo: {
|
||||
pic: {
|
||||
textSummary: 'Nya~',
|
||||
},
|
||||
ptt: {
|
||||
bytesReserve: Buffer.from([0x08, 0x00, 0x38, 0x00]),
|
||||
bytesGeneralFlags: Buffer.from([0x9a, 0x01, 0x0b, 0xaa, 0x03, 0x08, 0x08, 0x04, 0x12, 0x04, 0x00, 0x00, 0x00, 0x00]),
|
||||
},
|
||||
},
|
||||
clientSeq: 0,
|
||||
noNeedCompatMsg: false,
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x126D, 100, data, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new UploadPrivatePtt();
|
||||
@@ -0,0 +1,101 @@
|
||||
import * as proto from '@/snowcat-core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from 'snowcat-protobuf';
|
||||
import { OidbPacket, PacketTransformer } from '@/snowcat-core/packet/transformer/base';
|
||||
import OidbBase from '@/snowcat-core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgVideoElement } from '@/snowcat-core/packet/message/element';
|
||||
|
||||
class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
build (peerUin: string, video: PacketMsgVideoElement): OidbPacket {
|
||||
if (!video.fileSize || !video.thumbSize) throw new Error('video.fileSize or video.thumbSize is empty');
|
||||
const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
requestId: 3,
|
||||
command: 100,
|
||||
},
|
||||
scene: {
|
||||
requestType: 2,
|
||||
businessType: 2,
|
||||
sceneType: 1,
|
||||
c2C: {
|
||||
accountType: 2,
|
||||
targetUid: peerUin,
|
||||
},
|
||||
},
|
||||
client: {
|
||||
agentType: 2,
|
||||
},
|
||||
},
|
||||
upload: {
|
||||
uploadInfo: [
|
||||
{
|
||||
fileInfo: {
|
||||
fileSize: +video.fileSize,
|
||||
fileHash: video.fileMd5,
|
||||
fileSha1: video.fileSha1,
|
||||
fileName: video.fileName || 'video.mp4',
|
||||
type: {
|
||||
type: 2,
|
||||
picFormat: 0,
|
||||
videoFormat: video.fileFormat,
|
||||
voiceFormat: 0,
|
||||
},
|
||||
height: video.fileHeight ?? 0,
|
||||
width: video.fileWidth ?? 0,
|
||||
time: video.fileTime,
|
||||
original: 0,
|
||||
},
|
||||
subFileType: 0,
|
||||
}, {
|
||||
fileInfo: {
|
||||
fileSize: +video.thumbSize,
|
||||
fileHash: video.thumbMd5,
|
||||
fileSha1: video.thumbSha1,
|
||||
fileName: `${video.thumbMd5 || 'video-thumb'}.jpg`,
|
||||
type: {
|
||||
type: 1,
|
||||
picFormat: 0,
|
||||
videoFormat: 0,
|
||||
voiceFormat: 0,
|
||||
},
|
||||
height: video.thumbHeight,
|
||||
width: video.thumbWidth,
|
||||
time: 0,
|
||||
original: 0,
|
||||
},
|
||||
subFileType: 100,
|
||||
},
|
||||
],
|
||||
tryFastUploadCompleted: true,
|
||||
srvSendMsg: false,
|
||||
clientRandomId: crypto.randomBytes(8).readBigUInt64BE() & BigInt('0x7FFFFFFFFFFFFFFF'),
|
||||
compatQMsgSceneType: 2,
|
||||
extBizInfo: {
|
||||
pic: {
|
||||
bizType: 0,
|
||||
textSummary: 'Nya~',
|
||||
},
|
||||
video: {
|
||||
bytesPbReserve: Buffer.from([0x80, 0x01, 0x00]),
|
||||
},
|
||||
ptt: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
bytesReserve: Buffer.alloc(0),
|
||||
bytesGeneralFlags: Buffer.alloc(0),
|
||||
},
|
||||
},
|
||||
clientSeq: 0,
|
||||
noNeedCompatMsg: false,
|
||||
},
|
||||
});
|
||||
return OidbBase.build(0x11E9, 100, data, true, false);
|
||||
}
|
||||
|
||||
parse (data: Buffer) {
|
||||
const oidbBody = OidbBase.parse(data).body;
|
||||
return new NapProtoMsg(proto.NTV2RichMediaResp).decode(oidbBody);
|
||||
}
|
||||
}
|
||||
|
||||
export default new UploadPrivateVideo();
|
||||
@@ -0,0 +1,18 @@
|
||||
export { default as DownloadGroupFile } from './DownloadGroupFile';
|
||||
export { default as DownloadGroupPtt } from './DownloadGroupPtt';
|
||||
export { default as DownloadOfflineFile } from './DownloadOfflineFile';
|
||||
export { default as DownloadPrivateFile } from './DownloadPrivateFile';
|
||||
export { default as FetchSessionKey } from './FetchSessionKey';
|
||||
export { default as UploadGroupFile } from './UploadGroupFile';
|
||||
export { default as UploadGroupImage } from './UploadGroupImage';
|
||||
export { default as UploadGroupPtt } from './UploadGroupPtt';
|
||||
export { default as UploadGroupVideo } from './UploadGroupVideo';
|
||||
export { default as UploadPrivateFile } from './UploadPrivateFile';
|
||||
export { default as UploadPrivateImage } from './UploadPrivateImage';
|
||||
export { default as UploadPrivatePtt } from './UploadPrivatePtt';
|
||||
export { default as UploadPrivateVideo } from './UploadPrivateVideo';
|
||||
export { default as DownloadImage } from './DownloadImage';
|
||||
export { default as DownloadGroupImage } from './DownloadGroupImage';
|
||||
export { default as DownloadVideo } from './DownloadVideo';
|
||||
export { default as DownloadGroupVideo } from './DownloadGroupVideo';
|
||||
export { default as DownloadPtt } from './DownloadPtt';
|
||||
Reference in new issue
Block a user