diff --git a/packages/napcat-core/helper/forward-msg-builder.ts b/packages/napcat-core/helper/forward-msg-builder.ts index 9d5ced1d..6857df8d 100644 --- a/packages/napcat-core/helper/forward-msg-builder.ts +++ b/packages/napcat-core/helper/forward-msg-builder.ts @@ -2,14 +2,14 @@ import * as crypto from 'node:crypto'; import { PacketMsg } from '@/napcat-core/packet/message/message'; interface ForwardMsgJson { - app: string + app: string; config: ForwardMsgJsonConfig, desc: string, extra: ForwardMsgJsonExtra, meta: ForwardMsgJsonMeta, prompt: string, ver: string, - view: string + view: string; } interface ForwardMsgJsonConfig { @@ -17,7 +17,7 @@ interface ForwardMsgJsonConfig { forward: number, round: number, type: string, - width: number + width: number; } interface ForwardMsgJsonExtra { @@ -26,17 +26,17 @@ interface ForwardMsgJsonExtra { } interface ForwardMsgJsonMeta { - detail: ForwardMsgJsonMetaDetail + detail: ForwardMsgJsonMetaDetail; } interface ForwardMsgJsonMetaDetail { news: { - text: string + text: string; }[], resid: string, source: string, summary: string, - uniseq: string + uniseq: string; } interface ForwardAdaptMsg { @@ -50,8 +50,8 @@ interface ForwardAdaptMsgElement { } export class ForwardMsgBuilder { - private static build (resId: string, msg: ForwardAdaptMsg[], source?: string, news?: ForwardMsgJsonMetaDetail['news'], summary?: string, prompt?: string): ForwardMsgJson { - const id = crypto.randomUUID(); + private static build (resId: string, msg: ForwardAdaptMsg[], source?: string, news?: ForwardMsgJsonMetaDetail['news'], summary?: string, prompt?: string, uuid?: string): ForwardMsgJson { + const id = uuid ?? crypto.randomUUID(); const isGroupMsg = msg.some(m => m.isGroupMsg); if (!source) { source = msg.length === 0 ? '聊天记录' : (isGroupMsg ? '群聊的聊天记录' : msg.map(m => m.senderName).filter((v, i, a) => a.indexOf(v) === i).slice(0, 4).join('和') + '的聊天记录'); @@ -104,13 +104,19 @@ export class ForwardMsgBuilder { return this.build(resId, []); } - static fromPacketMsg (resId: string, packetMsg: PacketMsg[], source?: string, news?: ForwardMsgJsonMetaDetail['news'], summary?: string, prompt?: string): ForwardMsgJson { + static fromPacketMsg (resId: string, packetMsg: PacketMsg[], source?: string, news?: ForwardMsgJsonMetaDetail['news'], summary?: string, prompt?: string, uuid?: string): ForwardMsgJson { return this.build(resId, packetMsg.map(msg => ({ senderName: msg.senderName, isGroupMsg: msg.groupId !== undefined, msg: msg.msg.map(m => ({ preview: m.valid ? m.toPreview() : '[该消息类型暂不支持查看]', })), - })), source, news, summary, prompt); + })), + source, + news, + summary, + prompt, + uuid, + ); } } diff --git a/packages/napcat-core/packet/context/operationContext.ts b/packages/napcat-core/packet/context/operationContext.ts index b1312687..df5e250a 100644 --- a/packages/napcat-core/packet/context/operationContext.ts +++ b/packages/napcat-core/packet/context/operationContext.ts @@ -18,6 +18,7 @@ import { OidbPacket } from '@/napcat-core/packet/transformer/base'; import { ImageOcrResult } from '@/napcat-core/packet/entities/ocrResult'; import { gunzipSync } from 'zlib'; import { PacketMsgConverter } from '@/napcat-core/packet/message/converter'; +import { UploadForwardMsgParams } from '@/napcat-core/packet/transformer/message/UploadForwardMsgV2'; export class PacketOperationContext { private readonly context: PacketContext; @@ -26,7 +27,7 @@ export class PacketOperationContext { this.context = context; } - async sendPacket(pkt: OidbPacket, rsp?: T): Promise { + async sendPacket (pkt: OidbPacket, rsp?: T): Promise { return await this.context.client.sendOidbPacket(pkt, rsp); } @@ -224,7 +225,15 @@ export class PacketOperationContext { const res = trans.UploadForwardMsg.parse(resp); return res.result.resId; } - + async UploadForwardMsgV2 (msg: UploadForwardMsgParams[], groupUin: number = 0) { + //await this.SendPreprocess(msg, groupUin); + // 遍历上传资源 + await Promise.allSettled(msg.map(async (item) => { return await this.SendPreprocess(item.actionMsg, groupUin); })); + const req = trans.UploadForwardMsgV2.build(this.context.napcore.basicInfo.uid, msg, groupUin); + const resp = await this.context.client.sendOidbPacket(req, true); + const res = trans.UploadForwardMsg.parse(resp); + return res.result.resId; + } async MoveGroupFile ( groupUin: number, fileUUID: string, diff --git a/packages/napcat-core/packet/transformer/message/UploadForwardMsgV2.ts b/packages/napcat-core/packet/transformer/message/UploadForwardMsgV2.ts new file mode 100644 index 00000000..72348d34 --- /dev/null +++ b/packages/napcat-core/packet/transformer/message/UploadForwardMsgV2.ts @@ -0,0 +1,51 @@ +import zlib from 'node:zlib'; +import * as proto from '@/napcat-core/packet/transformer/proto'; +import { NapProtoMsg } from 'napcat-protobuf'; +import { OidbPacket, PacketBufBuilder, PacketTransformer } from '@/napcat-core/packet/transformer/base'; +import { PacketMsg } from '@/napcat-core/packet/message/message'; + +export interface UploadForwardMsgParams { + actionCommand: string; + actionMsg: PacketMsg[]; +} +class UploadForwardMsgV2 extends PacketTransformer { + build (selfUid: string, msg: UploadForwardMsgParams[], groupUin: number = 0): OidbPacket { + const reqdata = msg.map((item) => ({ + actionCommand: item.actionCommand, + actionData: { + msgBody: this.msgBuilder.buildFakeMsg(selfUid, item.actionMsg), + } + })); + const longMsgResultData = new NapProtoMsg(proto.LongMsgResult).encode( + { + action: reqdata, + } + ); + const payload = zlib.gzipSync(Buffer.from(longMsgResultData)); + const req = new NapProtoMsg(proto.SendLongMsgReq).encode( + { + info: { + type: groupUin === 0 ? 1 : 3, + uid: { + uid: groupUin === 0 ? selfUid : groupUin.toString(), + }, + groupUin, + payload, + }, + settings: { + field1: 4, field2: 1, field3: 7, field4: 0, + }, + } + ); + return { + cmd: 'trpc.group.long_msg_interface.MsgService.SsoSendLongMsg', + data: PacketBufBuilder(req), + }; + } + + parse (data: Buffer) { + return new NapProtoMsg(proto.SendLongMsgResp).decode(data); + } +} + +export default new UploadForwardMsgV2(); diff --git a/packages/napcat-core/packet/transformer/message/index.ts b/packages/napcat-core/packet/transformer/message/index.ts index 78e757c8..d471b316 100644 --- a/packages/napcat-core/packet/transformer/message/index.ts +++ b/packages/napcat-core/packet/transformer/message/index.ts @@ -2,3 +2,4 @@ export { default as UploadForwardMsg } from './UploadForwardMsg'; export { default as FetchGroupMessage } from './FetchGroupMessage'; export { default as FetchC2CMessage } from './FetchC2CMessage'; export { default as DownloadForwardMsg } from './DownloadForwardMsg'; +export { default as UploadForwardMsgV2 } from './UploadForwardMsgV2'; \ No newline at end of file diff --git a/packages/napcat-onebot/action/msg/SendMsg.ts b/packages/napcat-onebot/action/msg/SendMsg.ts index 2eaef166..ec3aef27 100644 --- a/packages/napcat-onebot/action/msg/SendMsg.ts +++ b/packages/napcat-onebot/action/msg/SendMsg.ts @@ -17,6 +17,7 @@ import { rawMsgWithSendMsg } from 'napcat-core/packet/message/converter'; import { Static, Type } from '@sinclair/typebox'; import { MsgActionsExamples } from '@/napcat-onebot/action/msg/examples'; import { OB11MessageMixTypeSchema } from '@/napcat-onebot/types/message'; +import { UploadForwardMsgParams } from '@/napcat-core/packet/transformer/message/UploadForwardMsgV2'; export const SendMsgPayloadSchema = Type.Object({ message_type: Type.Optional(Type.Union([Type.Literal('private'), Type.Literal('group')], { description: '消息类型 (private/group)' })), @@ -211,10 +212,13 @@ export class SendMsgBase extends OneBotAction { }, dp: number = 0): Promise<{ finallySendElements: SendArkElement, res_id?: string, + uuid?: string, + packetMsg: PacketMsg[], deleteAfterSentFiles: string[], } | null> { const packetMsg: PacketMsg[] = []; const delFiles: string[] = []; + const innerMsg: Array<{ uuid: string, packetMsg: PacketMsg[]; }> = new Array(); for (const node of messageNodes) { if (dp >= 3) { this.core.context.logger.logWarn('转发消息深度超过3层,将停止解析!'); @@ -232,6 +236,10 @@ export class SendMsgBase extends OneBotAction { }, dp + 1); sendElements = uploadReturnData?.finallySendElements ? [uploadReturnData.finallySendElements] : []; delFiles.push(...(uploadReturnData?.deleteAfterSentFiles || [])); + if (uploadReturnData?.uuid) { + innerMsg.push({ uuid: uploadReturnData.uuid, packetMsg: uploadReturnData.packetMsg }); + } + } else { const sendElementsCreateReturn = await this.obContext.apis.MsgApi.createSendElements(OB11Data, msgPeer); sendElements = sendElementsCreateReturn.sendElements; @@ -273,8 +281,19 @@ export class SendMsgBase extends OneBotAction { this.core.context.logger.logWarn('handleForwardedNodesPacket 元素为空!'); return null; } - const resid = await this.core.apis.PacketApi.pkt.operation.UploadForwardMsg(packetMsg, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0); - const forwardJson = ForwardMsgBuilder.fromPacketMsg(resid, packetMsg, source, news, summary, prompt); + const uploadMsgData: UploadForwardMsgParams[] = [{ + actionCommand: 'MultiMsg', + actionMsg: packetMsg, + }]; + innerMsg.forEach(({ uuid, packetMsg: msg }) => { + uploadMsgData.push({ + actionCommand: uuid, + actionMsg: msg, + }); + }); + const resid = await this.core.apis.PacketApi.pkt.operation.UploadForwardMsgV2(uploadMsgData, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0); + const uuid = crypto.randomUUID(); + const forwardJson = ForwardMsgBuilder.fromPacketMsg(resid, packetMsg, source, news, summary, prompt, uuid); return { deleteAfterSentFiles: delFiles, finallySendElements: { @@ -285,6 +304,8 @@ export class SendMsgBase extends OneBotAction { }, } as SendArkElement, res_id: resid, + uuid: uuid, + packetMsg: packetMsg, }; }