mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-21 09:36:35 +00:00
feat & refactor: add more packetElement & refactor packetMsg
This commit is contained in:
parent
524fd258d8
commit
698e095364
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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'));
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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 "[聊天记录]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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>[]
|
|
||||||
}
|
|
13
src/core/packet/msg/message.ts
Normal file
13
src/core/packet/msg/message.ts
Normal 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>[]
|
||||||
|
}
|
@ -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(
|
||||||
|
@ -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) {
|
||||||
|
@ -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, () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user