feat & refactor: add more packetElement & refactor packetMsg

This commit is contained in:
pk5ls20 2024-10-18 16:01:54 +08:00
parent 524fd258d8
commit 698e095364
No known key found for this signature in database
GPG Key ID: 6370ED7A169F493A
10 changed files with 119 additions and 38 deletions

View File

@ -23,7 +23,9 @@ export class LimitedHashTable<K, V> {
} }
while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) { while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) {
const oldestKey = this.keyToValue.keys().next().value; const oldestKey = this.keyToValue.keys().next().value;
// @ts-ignore
this.valueToKey.delete(this.keyToValue.get(oldestKey)!); this.valueToKey.delete(this.keyToValue.get(oldestKey)!);
// @ts-ignore
this.keyToValue.delete(oldestKey); this.keyToValue.delete(oldestKey);
} }
} }

View File

@ -8,9 +8,9 @@ import { NapProtoMsg } from '@/core/packet/proto/NapProto';
import { OidbSvcTrpcTcp0X9067_202_Rsp_Body } from '@/core/packet/proto/oidb/Oidb.0x9067_202'; import { OidbSvcTrpcTcp0X9067_202_Rsp_Body } from '@/core/packet/proto/oidb/Oidb.0x9067_202';
import { OidbSvcTrpcTcpBase, OidbSvcTrpcTcpBaseRsp } from '@/core/packet/proto/oidb/OidbBase'; import { OidbSvcTrpcTcpBase, OidbSvcTrpcTcpBaseRsp } from '@/core/packet/proto/oidb/OidbBase';
import { OidbSvcTrpcTcp0XFE1_2RSP } from '@/core/packet/proto/oidb/Oidb.fe1_2'; import { OidbSvcTrpcTcp0XFE1_2RSP } from '@/core/packet/proto/oidb/Oidb.fe1_2';
import { PacketForwardNode } from "@/core/packet/msg/entity/forward";
import {LogWrapper} from "@/common/log"; import {LogWrapper} from "@/common/log";
import {SendLongMsgResp} from "@/core/packet/proto/message/action"; import {SendLongMsgResp} from "@/core/packet/proto/message/action";
import {PacketMsg} from "@/core/packet/msg/message";
interface OffsetType { interface OffsetType {
[key: string]: { [key: string]: {
@ -106,7 +106,7 @@ export class NTQQPacketApi {
await this.sendPacket('OidbSvcTrpcTcp.0x8fc_2', data, true); await this.sendPacket('OidbSvcTrpcTcp.0x8fc_2', data, true);
} }
async sendUploadForwardMsg(msg: PacketForwardNode[], groupUin: number = 0) { async sendUploadForwardMsg(msg: PacketMsg[], groupUin: number = 0) {
const data = this.packetPacker.packUploadForwardMsg(this.core.selfInfo.uid, msg, groupUin); const data = this.packetPacker.packUploadForwardMsg(this.core.selfInfo.uid, msg, groupUin);
const ret = await this.sendPacket('trpc.group.long_msg_interface.MsgService.SsoSendLongMsg', data, true); const ret = await this.sendPacket('trpc.group.long_msg_interface.MsgService.SsoSendLongMsg', data, true);
const resp = new NapProtoMsg(SendLongMsgResp).decode(Buffer.from(ret.hex_data, 'hex')); const resp = new NapProtoMsg(SendLongMsgResp).decode(Buffer.from(ret.hex_data, 'hex'));

View File

@ -1,4 +1,4 @@
import assert from "node:assert"; import * as assert from "node:assert";
export class Frame{ export class Frame{
static pack(head: Buffer, body: Buffer): Buffer { static pack(head: Buffer, body: Buffer): Buffer {

View File

@ -1,8 +1,8 @@
import * as crypto from "crypto"; import * as crypto from "crypto";
import {PushMsgBody} from "@/core/packet/proto/message/message"; import {PushMsgBody} from "@/core/packet/proto/message/message";
import {NapProtoEncodeStructType} from "@/core/packet/proto/NapProto"; import {NapProtoEncodeStructType} from "@/core/packet/proto/NapProto";
import {PacketForwardNode} from "@/core/packet/msg/entity/forward";
import {LogWrapper} from "@/common/log"; import {LogWrapper} from "@/common/log";
import {PacketMsg} from "@/core/packet/msg/message";
export class PacketMsgBuilder { export class PacketMsgBuilder {
private logger: LogWrapper; private logger: LogWrapper;
@ -11,14 +11,14 @@ export class PacketMsgBuilder {
this.logger = logger; this.logger = logger;
} }
buildFakeMsg(selfUid: string, element: PacketForwardNode[]): NapProtoEncodeStructType<typeof PushMsgBody>[] { buildFakeMsg(selfUid: string, element: PacketMsg[]): 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.senderUin}&spec=640&img_type=jpg`;
const msgElement = node.msg.flatMap(msg => msg.buildElement() ?? []); const msgElement = node.msg.flatMap(msg => msg.buildElement() ?? []);
return { return {
responseHead: { responseHead: {
fromUid: "", fromUid: "",
fromUin: node.senderId, fromUin: node.senderUin,
toUid: node.groupId ? undefined : selfUid, toUid: node.groupId ? undefined : selfUid,
forward: node.groupId ? undefined : { forward: node.groupId ? undefined : {
friendName: node.senderName, friendName: node.senderName,

View File

@ -1,5 +1,6 @@
import assert from "node:assert"; import * as assert from "node:assert";
import * as zlib from "node:zlib"; import * as zlib from "node:zlib";
import * as crypto from "node:crypto";
import {NapProtoEncodeStructType, NapProtoMsg} from "@/core/packet/proto/NapProto"; import {NapProtoEncodeStructType, NapProtoMsg} from "@/core/packet/proto/NapProto";
import { import {
CustomFace, CustomFace,
@ -26,6 +27,7 @@ import {
SendVideoElement SendVideoElement
} from "@/core"; } from "@/core";
import {MsgInfo} from "@/core/packet/proto/oidb/common/Ntv2.RichMediaReq"; import {MsgInfo} from "@/core/packet/proto/oidb/common/Ntv2.RichMediaReq";
import {PacketMsg} from "@/core/packet/msg/message";
// raw <-> packet // raw <-> packet
// TODO: check ob11 -> raw impl! // TODO: check ob11 -> raw impl!
@ -42,6 +44,10 @@ export abstract class IPacketMsgElement<T extends SendMessageElement | SendStruc
buildElement(): NapProtoEncodeStructType<typeof Elem>[] | undefined { buildElement(): NapProtoEncodeStructType<typeof Elem>[] | undefined {
return undefined; return undefined;
} }
toPreview(): string {
return '[nya~]';
}
} }
export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> { export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> {
@ -59,6 +65,10 @@ export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> {
} }
}]; }];
} }
toPreview(): string {
return this.text;
}
} }
export class PacketMsgAtElement extends PacketMsgTextElement { export class PacketMsgAtElement extends PacketMsgTextElement {
@ -85,6 +95,10 @@ export class PacketMsgAtElement extends PacketMsgTextElement {
} }
}]; }];
} }
toPreview(): string {
return `@${this.targetUid} ${this.text}`;
}
} }
export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> { export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
@ -121,6 +135,10 @@ export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
} }
}] }]
} }
toPreview(): string {
return "[图片]";
}
} }
export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> { export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
@ -169,6 +187,10 @@ export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
} : undefined, } : undefined,
}] }]
} }
toPreview(): string {
return "[回复]";
}
} }
export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> { export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
@ -218,6 +240,10 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
}] }]
} }
} }
toPreview(): string {
return "[表情]";
}
} }
export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> { export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> {
@ -256,6 +282,10 @@ export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement>
} }
}] }]
} }
toPreview(): string {
return "[小程序]";
}
} }
export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElement> { export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElement> {
@ -277,23 +307,67 @@ export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElem
} }
}] }]
} }
toPreview(): string {
return this.content;
}
} }
// TODO: export class PacketMultiMsgElement extends IPacketMsgElement<SendStructLongMsgElement> {
// export class PacketMsgLongMsgElement extends IPacketMsgElement<SendStructLongMsgElement> { resid: string;
// resid: string; message: PacketMsg[];
//
// constructor(element: SendStructLongMsgElement) { constructor(rawElement: SendStructLongMsgElement)
// super(element); constructor(rawElement: SendStructLongMsgElement, message?: PacketMsg[]) {
// this.resid = element.structLongMsgElement.resId; super(rawElement);
// } this.resid = rawElement.structLongMsgElement.resId;
// this.message = message ?? [];
// buildElement(): NapProtoEncodeStructType<typeof Elem>[] { }
// return [{
// generalFlags: { buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
// longTextResId: this.resid, const id = crypto.randomUUID();
// longTextFlag: 1 const elementJson = {
// } app: "com.tencent.multimsg",
// }] config: {
// } autosize: 1,
// } forward: 1,
round: 1,
type: "normal",
width: 300
},
desc: "[聊天记录]",
extra: {
filename: id,
tsum: this.message.length,
},
meta: {
detail: {
news: this.message.length === 0 ? [{
text: "[Nya~ This message is send from NapCat.Packet!]",
}] : this.message.map(packetMsg => ({
text: `${packetMsg.senderName}: ${packetMsg.msg.map(msg => msg.toPreview()).join('')}`,
})),
resid: this.resid,
source: "聊天记录",
summary: `查看${this.message.length}条转发消息`,
uniseq: id,
}
},
prompt: "[聊天记录]",
ver: "0.0.0.5",
view: "contact"
}
return [{
lightAppElem: {
data: Buffer.concat([
Buffer.from([0x01]),
zlib.deflateSync(Buffer.from(JSON.stringify(elementJson), 'utf-8'))
])
}
}]
}
toPreview(): string {
return "[聊天记录]";
}
}

View File

@ -1,10 +0,0 @@
import { IPacketMsgElement } from "@/core/packet/msg/element";
import { SendMessageElement } from "@/core";
export interface PacketForwardNode {
groupId?: number
senderId: number
senderName: string
time: number
msg: IPacketMsgElement<SendMessageElement>[]
}

View File

@ -0,0 +1,13 @@
import {IPacketMsgElement} from "@/core/packet/msg/element";
import {SendMessageElement} from "@/core";
export interface PacketMsg {
seq?: number;
clientSeq?: number;
groupId?: number;
senderUid: string;
senderUin: number;
senderName: string;
time: number;
msg: IPacketMsgElement<SendMessageElement>[]
}

View File

@ -11,9 +11,9 @@ import {NTV2RichMediaReq} from "@/core/packet/proto/oidb/common/Ntv2.RichMediaRe
import {HttpConn0x6ff_501} from "@/core/packet/proto/action/action"; import {HttpConn0x6ff_501} from "@/core/packet/proto/action/action";
import {LongMsgResult, SendLongMsgReq} from "@/core/packet/proto/message/action"; import {LongMsgResult, SendLongMsgReq} from "@/core/packet/proto/message/action";
import {PacketMsgBuilder} from "@/core/packet/msg/builder"; import {PacketMsgBuilder} from "@/core/packet/msg/builder";
import {PacketForwardNode} from "@/core/packet/msg/entity/forward";
import {PacketMsgPicElement} from "@/core/packet/msg/element"; import {PacketMsgPicElement} from "@/core/packet/msg/element";
import {LogWrapper} from "@/common/log"; import {LogWrapper} from "@/common/log";
import {PacketMsg} from "@/core/packet/msg/message";
export type PacketHexStr = string & { readonly hexNya: unique symbol }; export type PacketHexStr = string & { readonly hexNya: unique symbol };
@ -94,7 +94,7 @@ export class PacketPacker {
return this.toHexStr(this.packOidbPacket(0xfe1, 2, oidb_0xfe1_2)); return this.toHexStr(this.packOidbPacket(0xfe1, 2, oidb_0xfe1_2));
} }
packUploadForwardMsg(selfUid: string, msg: PacketForwardNode[], groupUin: number = 0): PacketHexStr { packUploadForwardMsg(selfUid: string, msg: PacketMsg[], groupUin: number = 0): PacketHexStr {
// this.logger.logDebug("packUploadForwardMsg START!!!", selfUid, msg, groupUin); // this.logger.logDebug("packUploadForwardMsg START!!!", selfUid, msg, groupUin);
const msgBody = this.packetBuilder.buildFakeMsg(selfUid, msg); const msgBody = this.packetBuilder.buildFakeMsg(selfUid, msg);
const longMsgResultData = new NapProtoMsg(LongMsgResult).encode( const longMsgResultData = new NapProtoMsg(LongMsgResult).encode(

View File

@ -38,6 +38,7 @@ export default class SetAvatar extends BaseAction<Payload, null> {
throw `头像${payload.file}设置失败,api无返回`; throw `头像${payload.file}设置失败,api无返回`;
} }
// log(`头像设置返回:${JSON.stringify(ret)}`) // log(`头像设置返回:${JSON.stringify(ret)}`)
// @ts-ignore
if (ret['result'] == 1004022) { if (ret['result'] == 1004022) {
throw `头像${payload.file}设置失败,文件可能不是图片格式`; throw `头像${payload.file}设置失败,文件可能不是图片格式`;
} else if (ret['result'] != 0) { } else if (ret['result'] != 0) {

View File

@ -64,6 +64,7 @@ export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
}); });
this.app.use((req, res, next) => this.authorize(this.token, req, res, next)); this.app.use((req, res, next) => this.authorize(this.token, req, res, next));
// @ts-ignore
this.app.use((req, res) => this.handleRequest(req, res)); this.app.use((req, res) => this.handleRequest(req, res));
this.server.listen(this.port, () => { this.server.listen(this.port, () => {