From 17c37ec32f92f4c2c10979bb14ea93f1cb406895 Mon Sep 17 00:00:00 2001 From: Clansty Date: Fri, 25 Oct 2024 19:37:04 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E5=B5=8C=E5=A5=97=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E8=BD=AC=E5=8F=91=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/onebot/action/msg/SendMsg.ts | 48 +++++++++++++++++++++++--------- src/onebot/types/message.ts | 4 +++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/onebot/action/msg/SendMsg.ts b/src/onebot/action/msg/SendMsg.ts index f0536190..724b1118 100644 --- a/src/onebot/action/msg/SendMsg.ts +++ b/src/onebot/action/msg/SendMsg.ts @@ -145,9 +145,8 @@ export class SendMsg extends BaseAction { return { message_id: returnMsg!.id! }; } - // TODO: recursively handle forwarded nodes - private async handleForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: { text: string }[], summary?: string, prompt?: string): Promise<{ - message: RawMessage | null, + private async uploadForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: { text: string }[], summary?: string, prompt?: string): Promise<{ + finallySendElements: SendArkElement, res_id?: string }> { const logger = this.core.context.logger; @@ -155,7 +154,17 @@ export class SendMsg extends BaseAction { for (const node of messageNodes) { if ((node.data.id && typeof node.data.content !== "string") || !node.data.id) { const OB11Data = normalize(node.data.content); - const { sendElements } = await this.obContext.apis.MsgApi.createSendElements(OB11Data, msgPeer); + 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 { + 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, @@ -173,20 +182,33 @@ export class SendMsg extends BaseAction { } 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); - const finallySendElements = { - elementType: ElementType.ARK, - elementId: "", - arkElement: { - bytesData: JSON.stringify(forwardJson), - }, - } as SendArkElement; - let returnMsg: RawMessage | undefined; + return { + finallySendElements: { + elementType: ElementType.ARK, + elementId: "", + arkElement: { + bytesData: JSON.stringify(forwardJson), + }, + } as SendArkElement, + res_id: resid, + }; + } + + 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: resid }; + return { message: returnMsg ?? null, res_id }; } private async handleForwardedNodes(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<{ diff --git a/src/onebot/types/message.ts b/src/onebot/types/message.ts index 37830023..f73852ba 100644 --- a/src/onebot/types/message.ts +++ b/src/onebot/types/message.ts @@ -152,6 +152,10 @@ export interface OB11MessageNode { user_id?: number | string // number nickname: string content: OB11MessageMixType + source?: string, + news?: { text: string }[], + summary?: string, + prompt?: string }; } From e7a082c91c0467d5a5a6c6797d75e62e2c057208 Mon Sep 17 00:00:00 2001 From: pk5ls20 Date: Fri, 25 Oct 2024 22:10:24 +0800 Subject: [PATCH 2/2] 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<{