feat: add more msgElement

This commit is contained in:
pk5ls20
2024-10-18 04:35:23 +08:00
parent 0cb68d3737
commit e4a533e7b7
5 changed files with 211 additions and 51 deletions

View File

@@ -372,6 +372,7 @@ export interface ReplyElement {
senderUin: string; senderUin: string;
senderUidStr?: string; senderUidStr?: string;
replyMsgTime?: string; replyMsgTime?: string;
replyMsgClientSeq?: string;
} }
export interface SendReplyElement { export interface SendReplyElement {
@@ -391,7 +392,7 @@ export interface SendMarketFaceElement {
marketFaceElement: MarketFaceElement; marketFaceElement: MarketFaceElement;
} }
export interface SendstructLongMsgElement { export interface SendStructLongMsgElement {
elementType: ElementType.STRUCTLONGMSG; elementType: ElementType.STRUCTLONGMSG;
elementId: string; elementId: string;
structLongMsgElement: StructLongMsgElement; structLongMsgElement: StructLongMsgElement;

View File

@@ -127,7 +127,7 @@ export class PacketHighwaySession {
extend extend
); );
} else { } else {
this.logger.logError(`[Highway] get upload invalid ukey ${ukey}, don't need upload!`); this.logger.logDebug(`[Highway] get upload invalid ukey ${ukey}, don't need upload!`);
} }
img.msgInfo = preRespData.upload.msgInfo; img.msgInfo = preRespData.upload.msgInfo;
// img.groupPicExt = new NapProtoMsg(CustomFace).decode(preRespData.tcpUpload.compatQMsg) // img.groupPicExt = new NapProtoMsg(CustomFace).decode(preRespData.tcpUpload.compatQMsg)

View File

@@ -14,8 +14,7 @@ export class PacketMsgBuilder {
buildFakeMsg(selfUid: string, element: PacketForwardNode[]): NapProtoEncodeStructType<typeof PushMsgBody>[] { buildFakeMsg(selfUid: string, element: PacketForwardNode[]): NapProtoEncodeStructType<typeof PushMsgBody>[] {
return element.map((node): NapProtoEncodeStructType<typeof PushMsgBody> => { return element.map((node): NapProtoEncodeStructType<typeof PushMsgBody> => {
const avatar = `https://q.qlogo.cn/headimg_dl?dst_uin=${node.senderId}&spec=640&img_type=jpg`; const avatar = `https://q.qlogo.cn/headimg_dl?dst_uin=${node.senderId}&spec=640&img_type=jpg`;
const msgElement = node.msg.map((msg) => msg.buildElement() ?? []); const msgElement = node.msg.flatMap(msg => msg.buildElement() ?? []);
// this.logger.logDebug(`NOW MSG ELEMENT: ${JSON.stringify(msgElement)}`);
return { return {
responseHead: { responseHead: {
fromUid: "", fromUid: "",

View File

@@ -1,16 +1,27 @@
import assert from "node:assert"; import assert from "node:assert";
import * as zlib from "node:zlib";
import {NapProtoEncodeStructType, NapProtoMsg} from "@/core/packet/proto/NapProto"; import {NapProtoEncodeStructType, NapProtoMsg} from "@/core/packet/proto/NapProto";
import {CustomFace, Elem, MentionExtra, NotOnlineImage} from "@/core/packet/proto/message/element"; import {
CustomFace,
Elem,
MarkdownData,
MentionExtra,
NotOnlineImage,
QBigFaceExtra,
QSmallFaceExtra
} from "@/core/packet/proto/message/element";
import { import {
AtType, AtType,
PicType, PicType,
SendArkElement, SendArkElement,
SendFaceElement, SendFaceElement,
SendFileElement, SendFileElement,
SendMarkdownElement,
SendMessageElement, SendMessageElement,
SendPicElement, SendPicElement,
SendPttElement, SendPttElement,
SendReplyElement, SendReplyElement,
SendStructLongMsgElement,
SendTextElement, SendTextElement,
SendVideoElement SendVideoElement
} from "@/core"; } from "@/core";
@@ -19,7 +30,8 @@ import {MsgInfo} from "@/core/packet/proto/oidb/common/Ntv2.RichMediaReq";
// raw <-> packet // raw <-> packet
// TODO: check ob11 -> raw impl! // TODO: check ob11 -> raw impl!
// TODO: parse to raw element // TODO: parse to raw element
export abstract class IPacketMsgElement<T extends SendMessageElement> { // TODO: SendStructLongMsgElement
export abstract class IPacketMsgElement<T extends SendMessageElement | SendStructLongMsgElement> {
protected constructor(rawElement: T) { protected constructor(rawElement: T) {
} }
@@ -27,7 +39,7 @@ export abstract class IPacketMsgElement<T extends SendMessageElement> {
return undefined; return undefined;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem> | undefined { buildElement(): NapProtoEncodeStructType<typeof Elem>[] | undefined {
return undefined; return undefined;
} }
} }
@@ -40,12 +52,12 @@ export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> {
this.text = element.textElement.content; this.text = element.textElement.content;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem> { buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return { return [{
text: { text: {
str: this.text str: this.text
} }
}; }];
} }
} }
@@ -59,20 +71,19 @@ export class PacketMsgAtElement extends PacketMsgTextElement {
this.atAll = element.textElement.atType === AtType.atAll; this.atAll = element.textElement.atType === AtType.atAll;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem> { buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
const res = new NapProtoMsg(MentionExtra).encode({ return [{
type: this.atAll ? 1 : 2,
uin: 0,
field5: 0,
uid: this.targetUid,
}
);
return {
text: { text: {
str: this.text, str: this.text,
pbReserve: res pbReserve: new NapProtoMsg(MentionExtra).encode({
type: this.atAll ? 1 : 2,
uin: 0,
field5: 0,
uid: this.targetUid,
}
)
} }
}; }];
} }
} }
@@ -100,15 +111,112 @@ export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
this.picType = element.picElement.picType; this.picType = element.picElement.picType;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem> { buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
assert(this.msgInfo !== null, 'msgInfo is null, expected not null'); assert(this.msgInfo !== null, 'msgInfo is null, expected not null');
return { return [{
commonElem: { commonElem: {
serviceType: 48, serviceType: 48,
pbElem: new NapProtoMsg(MsgInfo).encode(this.msgInfo), pbElem: new NapProtoMsg(MsgInfo).encode(this.msgInfo),
businessType: 10, businessType: 10,
} }
} as NapProtoEncodeStructType<typeof Elem> }]
}
}
export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
messageId: bigint;
messageSeq: number;
messageClientSeq: number;
targetUin: number;
targetUid: string;
time: number;
constructor(element: SendReplyElement) {
super(element);
this.messageId = BigInt(element.replyElement.replayMsgId ?? 0);
this.messageSeq = Number(element.replyElement.replayMsgSeq ?? 0);
this.messageClientSeq = Number(element.replyElement.replyMsgClientSeq ?? 0);
this.targetUin = Number(element.replyElement.senderUin ?? 0);
this.targetUid = element.replyElement.senderUidStr ?? '';
this.time = Number(element.replyElement.replyMsgTime ?? 0);
}
get isGroupReply(): boolean {
return this.messageClientSeq !== 0;
}
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{
srcMsg: {
origSeqs: [this.isGroupReply ? this.messageClientSeq : this.messageSeq],
senderUin: BigInt(this.targetUin),
time: this.time,
elems: [], // TODO: in replyElement.sourceMsgTextElems
pbReserve: {
messageId: this.messageId,
},
toUin: BigInt(0),
}
}, {
text: this.isGroupReply ? {
str: 'nya~',
pbReserve: new NapProtoMsg(MentionExtra).encode({
type: this.targetUin === 0 ? 1 : 2,
uin: 0,
field5: 0,
uid: String(this.targetUid),
}),
} : undefined,
}]
}
}
export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
faceId: number;
isLargeFace: boolean;
constructor(element: SendFaceElement) {
super(element);
this.faceId = element.faceElement.faceIndex;
this.isLargeFace = element.faceElement.faceType === 3;
}
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
if (this.isLargeFace) {
return [{
commonElem: {
serviceType: 37,
pbElem: new NapProtoMsg(QBigFaceExtra).encode({
aniStickerPackId: "1",
aniStickerId: "8",
faceId: this.faceId,
field4: 1,
field6: "",
preview: "",
field9: 1
}),
businessType: 1
}
}]
} else if (this.faceId < 260) {
return [{
face: {
index: this.faceId
}
}];
} else {
return [{
commonElem: {
serviceType: 33,
pbElem: new NapProtoMsg(QSmallFaceExtra).encode({
faceId: this.faceId,
preview: "",
preview2: ""
}),
businessType: 1
}
}]
}
} }
} }
@@ -118,33 +226,74 @@ export class PacketMsgPttElement extends IPacketMsgElement<SendPttElement> {
} }
} }
export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
constructor(element: SendReplyElement) {
super(element);
}
}
export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
constructor(element: SendFaceElement) {
super(element);
}
}
export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
constructor(element: SendFileElement) {
super(element);
}
}
export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> { export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> {
constructor(element: SendVideoElement) { constructor(element: SendVideoElement) {
super(element); super(element);
} }
} }
export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement> { export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
constructor(element: SendArkElement) { constructor(element: SendFileElement) {
super(element); super(element);
} }
} }
export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement> {
payload: string;
constructor(element: SendArkElement) {
super(element);
this.payload = element.arkElement.bytesData;
}
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{
lightAppElem: {
data: Buffer.concat([
Buffer.from([0x01]),
zlib.deflateSync(Buffer.from(this.payload, 'utf-8'))
])
}
}]
}
}
// TODO:
// export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElement> {
// content: string;
//
// constructor(element: SendMarkdownElement) {
// super(element);
// this.content = element.markdownElement.content;
// }
//
// buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
// return [{
// commonElem: {
// serviceType: 45,
// pbElem: new NapProtoMsg(MarkdownData).encode({
// content: this.content
// }),
// businessType: 1
// }
// }]
// }
// }
//
// export class PacketMsgLongMsgElement extends IPacketMsgElement<SendStructLongMsgElement> {
// resid: string;
//
// constructor(element: SendStructLongMsgElement) {
// super(element);
// this.resid = element.structLongMsgElement.resId;
// }
//
// buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
// return [{
// generalFlags: {
// longTextResId: this.resid,
// longTextFlag: 1
// }
// }]
// }
// }

View File

@@ -300,12 +300,19 @@ export const SrcMsg = {
elems: ProtoField(5, () => Elem, false, true), elems: ProtoField(5, () => Elem, false, true),
type: ProtoField(6, ScalarType.INT32, true), type: ProtoField(6, ScalarType.INT32, true),
richMsg: ProtoField(7, ScalarType.BYTES, true), richMsg: ProtoField(7, ScalarType.BYTES, true),
pbReserve: ProtoField(8, ScalarType.BYTES, true), pbReserve: ProtoField(8, () => SrcMsgPbRes, true),
sourceMsg: ProtoField(9, ScalarType.BYTES, true), sourceMsg: ProtoField(9, ScalarType.BYTES, true),
toUin: ProtoField(10, ScalarType.UINT64, true), toUin: ProtoField(10, ScalarType.UINT64, true),
troopName: ProtoField(11, ScalarType.BYTES, true), troopName: ProtoField(11, ScalarType.BYTES, true),
}; };
export const SrcMsgPbRes = {
messageId: ProtoField(3, ScalarType.UINT64),
senderUid: ProtoField(6, ScalarType.STRING, true),
receiverUid: ProtoField(7, ScalarType.STRING, true),
friendSeq: ProtoField(8, ScalarType.UINT32, true),
}
export const LightAppElem = { export const LightAppElem = {
data: ProtoField(1, ScalarType.BYTES), data: ProtoField(1, ScalarType.BYTES),
msgResid: ProtoField(2, ScalarType.BYTES, true), msgResid: ProtoField(2, ScalarType.BYTES, true),
@@ -328,12 +335,12 @@ export const MentionExtra = {
uid: ProtoField(9, ScalarType.STRING, true), uid: ProtoField(9, ScalarType.STRING, true),
}; };
export const QFaceExtra = { export const QBigFaceExtra = {
field1: ProtoField(1, ScalarType.STRING, true), AniStickerPackId: ProtoField(1, ScalarType.STRING, true),
field2: ProtoField(2, ScalarType.STRING, true), AniStickerId: ProtoField(2, ScalarType.STRING, true),
faceId: ProtoField(3, ScalarType.INT32, true), faceId: ProtoField(3, ScalarType.INT32, true),
field4: ProtoField(4, ScalarType.INT32, true), Field4: ProtoField(4, ScalarType.INT32, true),
field5: ProtoField(5, ScalarType.INT32, true), AniStickerType: ProtoField(5, ScalarType.INT32, true),
field6: ProtoField(6, ScalarType.STRING, true), field6: ProtoField(6, ScalarType.STRING, true),
preview: ProtoField(7, ScalarType.STRING, true), preview: ProtoField(7, ScalarType.STRING, true),
field9: ProtoField(9, ScalarType.INT32, true), field9: ProtoField(9, ScalarType.INT32, true),
@@ -344,3 +351,7 @@ export const QSmallFaceExtra = {
preview: ProtoField(2, ScalarType.STRING), preview: ProtoField(2, ScalarType.STRING),
preview2: ProtoField(3, ScalarType.STRING), preview2: ProtoField(3, ScalarType.STRING),
}; };
export const MarkdownData = {
content: ProtoField(1, ScalarType.STRING)
}