mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
feat: add more msgElement
This commit is contained in:
@@ -372,6 +372,7 @@ export interface ReplyElement {
|
||||
senderUin: string;
|
||||
senderUidStr?: string;
|
||||
replyMsgTime?: string;
|
||||
replyMsgClientSeq?: string;
|
||||
}
|
||||
|
||||
export interface SendReplyElement {
|
||||
@@ -391,7 +392,7 @@ export interface SendMarketFaceElement {
|
||||
marketFaceElement: MarketFaceElement;
|
||||
}
|
||||
|
||||
export interface SendstructLongMsgElement {
|
||||
export interface SendStructLongMsgElement {
|
||||
elementType: ElementType.STRUCTLONGMSG;
|
||||
elementId: string;
|
||||
structLongMsgElement: StructLongMsgElement;
|
||||
|
@@ -127,7 +127,7 @@ export class PacketHighwaySession {
|
||||
extend
|
||||
);
|
||||
} 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.groupPicExt = new NapProtoMsg(CustomFace).decode(preRespData.tcpUpload.compatQMsg)
|
||||
|
@@ -14,8 +14,7 @@ export class PacketMsgBuilder {
|
||||
buildFakeMsg(selfUid: string, element: PacketForwardNode[]): 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 msgElement = node.msg.map((msg) => msg.buildElement() ?? []);
|
||||
// this.logger.logDebug(`NOW MSG ELEMENT: ${JSON.stringify(msgElement)}`);
|
||||
const msgElement = node.msg.flatMap(msg => msg.buildElement() ?? []);
|
||||
return {
|
||||
responseHead: {
|
||||
fromUid: "",
|
||||
|
@@ -1,16 +1,27 @@
|
||||
import assert from "node:assert";
|
||||
import * as zlib from "node:zlib";
|
||||
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 {
|
||||
AtType,
|
||||
PicType,
|
||||
SendArkElement,
|
||||
SendFaceElement,
|
||||
SendFileElement,
|
||||
SendMarkdownElement,
|
||||
SendMessageElement,
|
||||
SendPicElement,
|
||||
SendPttElement,
|
||||
SendReplyElement,
|
||||
SendStructLongMsgElement,
|
||||
SendTextElement,
|
||||
SendVideoElement
|
||||
} from "@/core";
|
||||
@@ -19,7 +30,8 @@ import {MsgInfo} from "@/core/packet/proto/oidb/common/Ntv2.RichMediaReq";
|
||||
// raw <-> packet
|
||||
// TODO: check ob11 -> raw impl!
|
||||
// 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) {
|
||||
}
|
||||
|
||||
@@ -27,7 +39,7 @@ export abstract class IPacketMsgElement<T extends SendMessageElement> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem> | undefined {
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -40,12 +52,12 @@ export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> {
|
||||
this.text = element.textElement.content;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem> {
|
||||
return {
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
text: {
|
||||
str: this.text
|
||||
}
|
||||
};
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,20 +71,19 @@ export class PacketMsgAtElement extends PacketMsgTextElement {
|
||||
this.atAll = element.textElement.atType === AtType.atAll;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem> {
|
||||
const res = new NapProtoMsg(MentionExtra).encode({
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
text: {
|
||||
str: this.text,
|
||||
pbReserve: new NapProtoMsg(MentionExtra).encode({
|
||||
type: this.atAll ? 1 : 2,
|
||||
uin: 0,
|
||||
field5: 0,
|
||||
uid: this.targetUid,
|
||||
}
|
||||
);
|
||||
return {
|
||||
text: {
|
||||
str: this.text,
|
||||
pbReserve: res
|
||||
)
|
||||
}
|
||||
};
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,15 +111,112 @@ export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
|
||||
this.picType = element.picElement.picType;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem> {
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
assert(this.msgInfo !== null, 'msgInfo is null, expected not null');
|
||||
return {
|
||||
return [{
|
||||
commonElem: {
|
||||
serviceType: 48,
|
||||
pbElem: new NapProtoMsg(MsgInfo).encode(this.msgInfo),
|
||||
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> {
|
||||
constructor(element: SendVideoElement) {
|
||||
super(element);
|
||||
}
|
||||
}
|
||||
|
||||
export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement> {
|
||||
constructor(element: SendArkElement) {
|
||||
export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
|
||||
constructor(element: SendFileElement) {
|
||||
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
|
||||
// }
|
||||
// }]
|
||||
// }
|
||||
// }
|
||||
|
@@ -300,12 +300,19 @@ export const SrcMsg = {
|
||||
elems: ProtoField(5, () => Elem, false, true),
|
||||
type: ProtoField(6, ScalarType.INT32, true),
|
||||
richMsg: ProtoField(7, ScalarType.BYTES, true),
|
||||
pbReserve: ProtoField(8, ScalarType.BYTES, true),
|
||||
pbReserve: ProtoField(8, () => SrcMsgPbRes, true),
|
||||
sourceMsg: ProtoField(9, ScalarType.BYTES, true),
|
||||
toUin: ProtoField(10, ScalarType.UINT64, 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 = {
|
||||
data: ProtoField(1, ScalarType.BYTES),
|
||||
msgResid: ProtoField(2, ScalarType.BYTES, true),
|
||||
@@ -328,12 +335,12 @@ export const MentionExtra = {
|
||||
uid: ProtoField(9, ScalarType.STRING, true),
|
||||
};
|
||||
|
||||
export const QFaceExtra = {
|
||||
field1: ProtoField(1, ScalarType.STRING, true),
|
||||
field2: ProtoField(2, ScalarType.STRING, true),
|
||||
export const QBigFaceExtra = {
|
||||
AniStickerPackId: ProtoField(1, ScalarType.STRING, true),
|
||||
AniStickerId: ProtoField(2, ScalarType.STRING, true),
|
||||
faceId: ProtoField(3, ScalarType.INT32, true),
|
||||
field4: ProtoField(4, ScalarType.INT32, true),
|
||||
field5: ProtoField(5, ScalarType.INT32, true),
|
||||
Field4: ProtoField(4, ScalarType.INT32, true),
|
||||
AniStickerType: ProtoField(5, ScalarType.INT32, true),
|
||||
field6: ProtoField(6, ScalarType.STRING, true),
|
||||
preview: ProtoField(7, ScalarType.STRING, true),
|
||||
field9: ProtoField(9, ScalarType.INT32, true),
|
||||
@@ -344,3 +351,7 @@ export const QSmallFaceExtra = {
|
||||
preview: ProtoField(2, ScalarType.STRING),
|
||||
preview2: ProtoField(3, ScalarType.STRING),
|
||||
};
|
||||
|
||||
export const MarkdownData = {
|
||||
content: ProtoField(1, ScalarType.STRING)
|
||||
}
|
||||
|
Reference in New Issue
Block a user