From e7a082c91c0467d5a5a6c6797d75e62e2c057208 Mon Sep 17 00:00:00 2001 From: pk5ls20 Date: Fri, 25 Oct 2024 22:10:24 +0800 Subject: [PATCH] feat: better recursive parsing with depth limits --- src/onebot/action/msg/SendMsg.ts | 70 ++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/onebot/action/msg/SendMsg.ts b/src/onebot/action/msg/SendMsg.ts index 724b1118..75f03975 100644 --- a/src/onebot/action/msg/SendMsg.ts +++ b/src/onebot/action/msg/SendMsg.ts @@ -116,9 +116,17 @@ export class SendMsg extends BaseAction { if (getSpecialMsgNum(payload, OB11MessageDataType.node)) { const packetMode = this.core.apis.PacketApi.available; - const returnMsgAndResId = packetMode - ? await this.handleForwardedNodesPacket(peer, messages as OB11MessageNode[], payload.source, payload.news, payload.summary, payload.prompt) - : await this.handleForwardedNodes(peer, messages as OB11MessageNode[]); + let returnMsgAndResId: { message: RawMessage | null, res_id?: string } | null; + try { + returnMsgAndResId = packetMode + ? await this.handleForwardedNodesPacket(peer, messages as OB11MessageNode[], payload.source, payload.news, payload.summary, payload.prompt) + : await this.handleForwardedNodes(peer, messages as OB11MessageNode[]); + } catch (e) { + throw Error(packetMode ? `发送伪造合并转发消息失败: ${e}` : `发送合并转发消息失败: ${e}`); + } + if (!returnMsgAndResId) { + throw Error('发送合并转发消息失败:returnMsgAndResId 为空!'); + } if (returnMsgAndResId.message) { const msgShortId = MessageUnique.createUniqueMsgId({ guildId: '', @@ -129,7 +137,6 @@ export class SendMsg extends BaseAction { } else if (returnMsgAndResId.res_id && !returnMsgAndResId.message) { throw Error(`发送转发消息(res_id:${returnMsgAndResId.res_id} 失败`); } - throw Error('发送转发消息失败'); } else { // if (getSpecialMsgNum(payload, OB11MessageDataType.music)) { // const music: OB11MessageCustomMusic = messages[0] as OB11MessageCustomMusic; @@ -145,29 +152,40 @@ export class SendMsg extends BaseAction { return { message_id: returnMsg!.id! }; } - private async uploadForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: { text: string }[], summary?: string, prompt?: string): Promise<{ + private async uploadForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: { + text: string + }[], summary?: string, prompt?: string, parentMeta?: { + user_id: string, + nickname: string, + }, dp: number = 0): Promise<{ finallySendElements: SendArkElement, res_id?: string - }> { + } | null> { const logger = this.core.context.logger; const packetMsg: PacketMsg[] = []; for (const node of messageNodes) { + if (dp >= 3) { + logger.logWarn('转发消息深度超过3层,将停止解析!'); + break; + } if ((node.data.id && typeof node.data.content !== "string") || !node.data.id) { - const OB11Data = normalize(node.data.content); + const OB11Data = normalize(node.type === OB11MessageDataType.node ? node.data.content : node); let sendElements: SendMessageElement[]; - if (getSpecialMsgNum({ message: OB11Data }, OB11MessageDataType.node)) { - const uploadReturnData = await this.uploadForwardedNodesPacket(msgPeer, OB11Data as OB11MessageNode[], node.data.source, node.data.news, node.data.summary, node.data.prompt); - sendElements = [uploadReturnData.finallySendElements]; - } - else { + if (getSpecialMsgNum({message: OB11Data}, OB11MessageDataType.node)) { + const uploadReturnData = await this.uploadForwardedNodesPacket(msgPeer, OB11Data as OB11MessageNode[], node.data.source, node.data.news, node.data.summary, node.data.prompt, { + user_id: node.data.user_id?.toString() ?? parentMeta?.user_id ?? this.core.selfInfo.uin, + nickname: node.data.nickname ?? parentMeta?.nickname ?? "QQ用户", + }, dp + 1); + sendElements = uploadReturnData?.finallySendElements ? [uploadReturnData.finallySendElements] : []; + } else { const sendElementsCreateReturn = await this.obContext.apis.MsgApi.createSendElements(OB11Data, msgPeer); sendElements = sendElementsCreateReturn.sendElements; } const packetMsgElements: rawMsgWithSendMsg = { - senderUin: Number(node.data.user_id) ?? +this.core.selfInfo.uin, - senderName: node.data.nickname, + senderUin: Number(node.data.user_id ?? parentMeta?.user_id) || +this.core.selfInfo.uin, + senderName: node.data.nickname ?? parentMeta?.nickname ?? "QQ用户", groupId: msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : undefined, time: Date.now(), msg: sendElements, @@ -180,6 +198,10 @@ export class SendMsg extends BaseAction { logger.logDebug(`handleForwardedNodesPacket 跳过元素 ${JSON.stringify(node)}`); } } + if (packetMsg.length === 0) { + logger.logWarn('handleForwardedNodesPacket 元素为空!'); + return null; + } const resid = await this.core.apis.PacketApi.sendUploadForwardMsg(packetMsg, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0); const forwardJson = ForwardMsgBuilder.fromPacketMsg(resid, packetMsg, source, news, summary, prompt); return { @@ -194,21 +216,19 @@ export class SendMsg extends BaseAction { }; } - private async handleForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: { text: string }[], summary?: string, prompt?: string): Promise<{ + private async handleForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: { + text: string + }[], summary?: string, prompt?: string): Promise<{ message: RawMessage | null, res_id?: string }> { - const logger = this.core.context.logger; let returnMsg: RawMessage | undefined, res_id: string | undefined; - try { - const uploadReturnData = await this.uploadForwardedNodesPacket(msgPeer, messageNodes, source, news, summary, prompt); - res_id = uploadReturnData.res_id; - const finallySendElements = uploadReturnData.finallySendElements; - returnMsg = await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(msgPeer, [finallySendElements], [], true).catch(_ => undefined); - } catch (e) { - logger.logWarn("发送伪造合并转发消息失败!", e); - } - return { message: returnMsg ?? null, res_id }; + const uploadReturnData = await this.uploadForwardedNodesPacket(msgPeer, messageNodes, source, news, summary, prompt); + res_id = uploadReturnData?.res_id; + const finallySendElements = uploadReturnData?.finallySendElements; + if (!finallySendElements) throw Error('转发消息失败,生成节点为空'); + returnMsg = await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(msgPeer, [finallySendElements], [], true).catch(_ => undefined); + return {message: returnMsg ?? null, res_id}; } private async handleForwardedNodes(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<{