Skip to content

Commit 6758825

Browse files
committed
feat: 聊天记录对聊天记录合并转发修复 & fix #1673
1 parent ae53d27 commit 6758825

File tree

4 files changed

+55
-10
lines changed

4 files changed

+55
-10
lines changed

packages/napcat-core/packet/context/operationContext.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,8 @@ export class PacketOperationContext {
230230
}
231231
async UploadForwardMsgV2 (msg: UploadForwardMsgParams[], groupUin: number = 0) {
232232
//await this.SendPreprocess(msg, groupUin);
233-
// 遍历上传资源
234-
await Promise.allSettled(msg.map(async (item) => { return await this.SendPreprocess(item.actionMsg, groupUin); }));
233+
// 遍历上传资源(跳过已有原始数据的项)
234+
await Promise.allSettled(msg.filter(item => item.actionMsg).map(async (item) => { return await this.SendPreprocess(item.actionMsg!, groupUin); }));
235235
const req = trans.UploadForwardMsgV2.build(this.context.napcore.basicInfo.uid, msg, groupUin);
236236
const resp = await this.context.client.sendOidbPacket(req, true);
237237
const res = trans.UploadForwardMsg.parse(resp);
@@ -312,6 +312,15 @@ export class PacketOperationContext {
312312
}
313313
}
314314

315+
async FetchForwardMsgRaw (resId: string) {
316+
const req = trans.DownloadForwardMsg.build(this.context.napcore.basicInfo.uid, resId);
317+
const resp = await this.context.client.sendOidbPacket(req, true);
318+
const res = trans.DownloadForwardMsg.parse(resp);
319+
const inflate = gunzipSync(res.result.payload);
320+
const result = new NapProtoMsg(LongMsgResult).decode(inflate);
321+
return result.action;
322+
}
323+
315324
async FetchForwardMsg (res_id: string): Promise<RawMessage[]> {
316325
const req = trans.DownloadForwardMsg.build(this.context.napcore.basicInfo.uid, res_id);
317326
const resp = await this.context.client.sendOidbPacket(req, true);

packages/napcat-core/packet/message/element.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as crypto from 'node:crypto';
12
import * as zlib from 'node:zlib';
23
import { NapProtoDecodeStructType, NapProtoEncodeStructType, NapProtoMsg } from 'napcat-protobuf';
34
import {
@@ -665,19 +666,21 @@ export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElem
665666
export class PacketMultiMsgElement extends IPacketMsgElement<SendMultiForwardMsgElement> {
666667
resid: string;
667668
message: PacketMsg[];
669+
uuid: string;
668670

669671
constructor (rawElement: SendMultiForwardMsgElement, message?: PacketMsg[]) {
670672
super(rawElement);
671673
this.resid = rawElement.multiForwardMsgElement.resId;
672674
this.message = message ?? [];
675+
this.uuid = rawElement.multiForwardMsgElement.fileName || crypto.randomUUID();
673676
}
674677

675678
override buildElement (): NapProtoEncodeStructType<typeof Elem>[] {
676679
return [{
677680
lightAppElem: {
678681
data: Buffer.concat([
679682
Buffer.from([0x01]),
680-
zlib.deflateSync(Buffer.from(JSON.stringify(ForwardMsgBuilder.fromPacketMsg(this.resid, this.message)), 'utf-8')),
683+
zlib.deflateSync(Buffer.from(JSON.stringify(ForwardMsgBuilder.fromPacketMsg(this.resid, this.message, undefined, undefined, undefined, undefined, this.uuid)), 'utf-8')),
681684
]),
682685
},
683686
}];

packages/napcat-core/packet/transformer/message/UploadForwardMsgV2.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import zlib from 'node:zlib';
22
import * as proto from '@/napcat-core/packet/transformer/proto';
3-
import { NapProtoMsg } from 'napcat-protobuf';
3+
import { NapProtoEncodeStructType, NapProtoMsg } from 'napcat-protobuf';
44
import { OidbPacket, PacketBufBuilder, PacketTransformer } from '@/napcat-core/packet/transformer/base';
55
import { PacketMsg } from '@/napcat-core/packet/message/message';
66

77
export interface UploadForwardMsgParams {
88
actionCommand: string;
9-
actionMsg: PacketMsg[];
9+
actionMsg?: PacketMsg[];
10+
actionMsgBody?: NapProtoEncodeStructType<typeof proto.PushMsgBody>[];
1011
}
1112
class UploadForwardMsgV2 extends PacketTransformer<typeof proto.SendLongMsgResp> {
1213
build (selfUid: string, msg: UploadForwardMsgParams[], groupUin: number = 0): OidbPacket {
1314
const reqdata = msg.map((item) => ({
1415
actionCommand: item.actionCommand,
1516
actionData: {
16-
msgBody: this.msgBuilder.buildFakeMsg(selfUid, item.actionMsg),
17+
msgBody: item.actionMsgBody ?? this.msgBuilder.buildFakeMsg(selfUid, item.actionMsg ?? []),
1718
}
1819
}));
1920
const longMsgResultData = new NapProtoMsg(proto.LongMsgResult).encode(

packages/napcat-onebot/action/msg/SendMsg.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,11 @@ export class SendMsgBase extends OneBotAction<SendMsgPayload, ReturnDataType> {
215215
uuid?: string,
216216
packetMsg: PacketMsg[],
217217
deleteAfterSentFiles: string[],
218-
innerPacketMsg?: Array<{ uuid: string, packetMsg: PacketMsg[]; }>;
218+
innerPacketMsg?: Array<{ uuid: string, packetMsg?: PacketMsg[], actionMsgBody?: UploadForwardMsgParams['actionMsgBody']; }>;
219219
} | null> {
220220
const packetMsg: PacketMsg[] = [];
221221
const delFiles: string[] = [];
222-
const innerMsg: Array<{ uuid: string, packetMsg: PacketMsg[]; }> = new Array();
222+
const innerMsg: Array<{ uuid: string, packetMsg?: PacketMsg[], actionMsgBody?: UploadForwardMsgParams['actionMsgBody']; }> = new Array();
223223
for (const node of messageNodes) {
224224
if (dp >= 3) {
225225
this.core.context.logger.logWarn('转发消息深度超过3层,将停止解析!');
@@ -240,7 +240,7 @@ export class SendMsgBase extends OneBotAction<SendMsgPayload, ReturnDataType> {
240240
if (uploadReturnData?.uuid) {
241241
innerMsg.push({ uuid: uploadReturnData.uuid, packetMsg: uploadReturnData.packetMsg });
242242
uploadReturnData.innerPacketMsg?.forEach(m => {
243-
innerMsg.push({ uuid: m.uuid, packetMsg: m.packetMsg });
243+
innerMsg.push(m);
244244
});
245245
}
246246

@@ -274,6 +274,37 @@ export class SendMsgBase extends OneBotAction<SendMsgPayload, ReturnDataType> {
274274
const msgCache = await this.core.apis.FileApi.downloadRawMsgMedia([msg]);
275275
delFiles.push(...msgCache);
276276
const transformedMsg = this.core.apis.PacketApi.pkt.msgConverter.rawMsgToPacketMsg(msg, msgPeer);
277+
// 检测嵌套合并转发消息,拉取内层protobuf数据
278+
for (const element of msg.elements) {
279+
let resId: string | undefined;
280+
let uuid: string | undefined;
281+
if (element.multiForwardMsgElement?.resId) {
282+
resId = element.multiForwardMsgElement.resId;
283+
uuid = element.multiForwardMsgElement.fileName;
284+
} else if (element.arkElement?.bytesData) {
285+
try {
286+
const json = JSON.parse(element.arkElement.bytesData);
287+
if (json.app === 'com.tencent.multimsg') {
288+
resId = json.meta?.detail?.resid;
289+
uuid = json.meta?.detail?.uniseq || json.extra?.filename;
290+
}
291+
} catch { /* not a valid json */ }
292+
}
293+
if (resId && uuid) {
294+
try {
295+
const rawActions = await this.core.apis.PacketApi.pkt.operation.FetchForwardMsgRaw(resId);
296+
for (const action of rawActions) {
297+
if (action.actionCommand === 'MultiMsg') {
298+
innerMsg.push({ uuid, actionMsgBody: action.actionData.msgBody });
299+
} else {
300+
innerMsg.push({ uuid: action.actionCommand, actionMsgBody: action.actionData.msgBody });
301+
}
302+
}
303+
} catch (e) {
304+
this.core.context.logger.logError(`获取合并转发内层消息失败: ${(e as Error)?.stack}`);
305+
}
306+
}
307+
}
277308
this.core.context.logger.logDebug(`handleForwardedNodesPacket[PureRaw] 转换为 ${stringifyWithBigInt(transformedMsg)}`);
278309
packetMsg.push(transformedMsg);
279310
}
@@ -289,10 +320,11 @@ export class SendMsgBase extends OneBotAction<SendMsgPayload, ReturnDataType> {
289320
actionCommand: 'MultiMsg',
290321
actionMsg: packetMsg,
291322
}];
292-
innerMsg.forEach(({ uuid, packetMsg: msg }) => {
323+
innerMsg.forEach(({ uuid, packetMsg: msg, actionMsgBody: raw }) => {
293324
uploadMsgData.push({
294325
actionCommand: uuid,
295326
actionMsg: msg,
327+
actionMsgBody: raw,
296328
});
297329
});
298330
const resid = await this.core.apis.PacketApi.pkt.operation.UploadForwardMsgV2(uploadMsgData, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0);

0 commit comments

Comments
 (0)