From a3e8c9b28a16462c26280a2c9dad78efdbcfcfff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Thu, 22 Aug 2024 14:58:05 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/entities/msg.ts | 5 +- src/onebot/api/index.ts | 3 +- src/onebot/api/msg.ts | 134 ++++++++++++++++++++++++++++++ src/onebot/helper/parseMessage.ts | 110 ++++-------------------- src/onebot/index.ts | 3 +- src/onebot/types/adapter.ts | 3 +- 6 files changed, 159 insertions(+), 99 deletions(-) create mode 100644 src/onebot/api/msg.ts diff --git a/src/core/entities/msg.ts b/src/core/entities/msg.ts index 01f4a050..6a611d47 100644 --- a/src/core/entities/msg.ts +++ b/src/core/entities/msg.ts @@ -362,6 +362,7 @@ export interface SendPicElement { } export interface ReplyElement { + sourceMsgIdInRecords?: string; replayMsgSeq: string; replayMsgId: string; senderUin: string; @@ -476,7 +477,7 @@ export interface MessageElement { extBufForUI: string,//"0x", textElement?: TextElement; faceElement?: FaceElement, - marketFaceElement?: MarkdownElement, + marketFaceElement?: MarketFaceElement, replyElement?: ReplyElement, picElement?: PicElement, pttElement?: PttElement, @@ -965,7 +966,7 @@ export interface RawMessage { records: RawMessage[]; - elements: ElementWrapper[]; + elements: MessageElement[]; } /** diff --git a/src/onebot/api/index.ts b/src/onebot/api/index.ts index 59c832bb..953379c8 100644 --- a/src/onebot/api/index.ts +++ b/src/onebot/api/index.ts @@ -1,3 +1,4 @@ export * from './friend'; export * from './group'; -export * from './user'; \ No newline at end of file +export * from './user'; +export * from './msg'; \ No newline at end of file diff --git a/src/onebot/api/msg.ts b/src/onebot/api/msg.ts new file mode 100644 index 00000000..41e195cb --- /dev/null +++ b/src/onebot/api/msg.ts @@ -0,0 +1,134 @@ +import { UUIDConverter } from '@/common/utils/helper'; +import { MessageUnique } from '@/common/utils/MessageUnique'; +import { AtType, ElementWrapper, MessageElement, NapCatCore, PicElement, RawMessage, ReplyElement, TextElement } from '@/core'; + +import { NapCatOneBot11Adapter, OB11MessageData, OB11MessageDataType } from '@/onebot'; + +export class OneBotMsgApi { + obContext: NapCatOneBot11Adapter; + coreContext: NapCatCore; + + constructor(obContext: NapCatOneBot11Adapter, coreContext: NapCatCore) { + this.obContext = obContext; + this.coreContext = coreContext; + } + async paseTextElemntWithAt(msg: RawMessage, textElement: TextElement) { + const NTQQUserApi = this.coreContext.apis.UserApi; + let message_data: OB11MessageData = { + data: {} as any, + type: 'unknown' as any, + }; + let qq: `${number}` | 'all'; + let name: string | undefined; + if (textElement.atType == AtType.atAll) { + qq = 'all'; + } else { + const { atNtUid, content } = textElement; + let atQQ = textElement.atUid; + if (!atQQ || atQQ === '0') { + atQQ = await NTQQUserApi.getUinByUidV2(atNtUid); + } + if (atQQ) { + qq = atQQ as `${number}`; + name = content.replace('@', ''); + } + } + message_data = { + type: OB11MessageDataType.at, + data: { + qq: qq!, + name, + }, + }; + return message_data; + } + async parseTextElement(msg: RawMessage, textElement: TextElement) { + let message_data: OB11MessageData = { + data: {} as any, + type: 'unknown' as any, + }; + message_data['type'] = OB11MessageDataType.text; + + let text = textElement.content; + if (!text.trim()) { + return false; + } + // 兼容 9.7.x 换行符 + if (text.indexOf('\n') === -1 && text.indexOf('\r\n') === -1) { + text = text.replace(/\r/g, '\n'); + } + message_data['data']['text'] = text; + return message_data; + } + async parsePicElement(msg: RawMessage, picElement: PicElement) { + const NTQQFileApi = this.coreContext.apis.FileApi; + let message_data: OB11MessageData = { + data: {} as any, + type: 'unknown' as any, + }; + message_data['type'] = OB11MessageDataType.image; + // message_data["data"]["file"] = element.picElement.sourcePath + message_data['data']['file'] = picElement.fileName; + message_data['data']['subType'] = picElement.picSubType; + message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); + // message_data["data"]["path"] = element.picElement.sourcePath + try { + message_data['data']['url'] = await NTQQFileApi.getImageUrl(picElement); + } catch (e: any) { + this.coreContext.context.logger.logError('获取图片url失败', e.stack); + } + //console.log(message_data['data']['url']) + // message_data["data"]["file_id"] = element.picElement.fileUuid + message_data['data']['file_size'] = picElement.fileSize; + return message_data; + } + async parseReplyElement(msg: RawMessage, replyElement: ReplyElement) { + const NTQQMsgApi = this.coreContext.apis.MsgApi; + let message_data: OB11MessageData = { + data: {} as any, + type: 'unknown' as any, + }; + message_data['type'] = OB11MessageDataType.reply; + //log("收到回复消息", element.replyElement); + try { + const records = msg.records.find(msgRecord => msgRecord.msgId === replyElement?.sourceMsgIdInRecords); + const peer = { + chatType: msg.chatType, + peerUid: msg.peerUid, + guildId: '', + }; + let replyMsg: RawMessage | undefined; + if (!records) throw new Error('找不到回复消息'); + replyMsg = (await NTQQMsgApi.getMsgsBySeqAndCount({ + peerUid: msg.peerUid, + guildId: '', + chatType: msg.chatType, + }, replyElement.replayMsgSeq, 1, true, true)).msgList.find(msg => msg.msgRandom === records.msgRandom); + if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) { + replyMsg = (await NTQQMsgApi.getSingleMsg(peer, replyElement.replayMsgSeq)).msgList[0]; + } + if (msg.peerUin == '284840486') { + //合并消息内侧 消息具体定位不到 + } + if ((!replyMsg || records.msgRandom !== replyMsg.msgRandom) && msg.peerUin !== '284840486') { + const replyMsgList = (await NTQQMsgApi.getMsgExBySeq(peer, records.msgSeq)).msgList; + if (replyMsgList.length < 1) { + throw new Error('回复消息消息验证失败'); + } + replyMsg = replyMsgList.filter(e => e.msgSeq == records.msgSeq).sort((a, b) => parseInt(a.msgTime) - parseInt(b.msgTime))[0]; + } + message_data['data']['id'] = MessageUnique.createMsg({ + peerUid: msg.peerUid, + guildId: '', + chatType: msg.chatType, + }, replyMsg.msgId)?.toString(); + //log("找到回复消息", message_data['data']['id'], replyMsg.msgList[0].msgId) + } catch (e: any) { + message_data['type'] = 'unknown' as any; + message_data['data'] = undefined; + this.coreContext.context.logger.logError('获取不到引用的消息', e.stack, replyElement.replayMsgSeq); + return undefined; + } + return message_data; + } +} diff --git a/src/onebot/helper/parseMessage.ts b/src/onebot/helper/parseMessage.ts index 83c0a322..d52e1881 100644 --- a/src/onebot/helper/parseMessage.ts +++ b/src/onebot/helper/parseMessage.ts @@ -78,97 +78,19 @@ export async function RawNTMsg2Onebot( type: 'unknown' as any, }; if (element.textElement && element.textElement?.atType !== AtType.notAt) { - let qq: `${number}` | 'all'; - let name: string | undefined; - if (element.textElement.atType == AtType.atAll) { - qq = 'all'; - } else { - const { atNtUid, content } = element.textElement; - let atQQ = element.textElement.atUid; - if (!atQQ || atQQ === '0') { - atQQ = await NTQQUserApi.getUinByUidV2(atNtUid); - } - if (atQQ) { - qq = atQQ as `${number}`; - name = content.replace('@', ''); - } - } - message_data = { - type: OB11MessageDataType.at, - data: { - qq: qq!, - name, - }, - }; + let textAtMsgData = await obcore.apiContext.MsgApi.paseTextElemntWithAt(msg, element.textElement); + if (textAtMsgData) message_data = textAtMsgData } else if (element.textElement) { - message_data['type'] = OB11MessageDataType.text; - - let text = element.textElement.content; - if (!text.trim()) { - continue; - } - // 兼容 9.7.x 换行符 - if (text.indexOf('\n') === -1 && text.indexOf('\r\n') === -1) { - text = text.replace(/\r/g, '\n'); - } - message_data['data']['text'] = text; + let textMsgData = await obcore.apiContext.MsgApi.parseTextElement(msg, element.textElement); + if (textMsgData) message_data = textMsgData; } else if (element.replyElement) { - message_data['type'] = OB11MessageDataType.reply; - //log("收到回复消息", element.replyElement); - try { - const records = msg.records.find(msgRecord => msgRecord.msgId === element?.replyElement?.sourceMsgIdInRecords); - const peer = { - chatType: msg.chatType, - peerUid: msg.peerUid, - guildId: '', - }; - let replyMsg: RawMessage | undefined; - if (!records) throw new Error('找不到回复消息'); - replyMsg = (await NTQQMsgApi.getMsgsBySeqAndCount({ - peerUid: msg.peerUid, - guildId: '', - chatType: msg.chatType, - }, element.replyElement.replayMsgSeq, 1, true, true)).msgList.find(msg => msg.msgRandom === records.msgRandom); - if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) { - replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replyElement.replayMsgSeq)).msgList[0]; - } - if (msg.peerUin == '284840486') { - //合并消息内侧 消息具体定位不到 - } - if ((!replyMsg || records.msgRandom !== replyMsg.msgRandom) && msg.peerUin !== '284840486') { - const replyMsgList = (await NTQQMsgApi.getMsgExBySeq(peer, records.msgSeq)).msgList; - if (replyMsgList.length < 1) { - throw new Error('回复消息消息验证失败'); - } - replyMsg = replyMsgList.filter(e => e.msgSeq == records.msgSeq).sort((a, b) => parseInt(a.msgTime) - parseInt(b.msgTime))[0]; - } - message_data['data']['id'] = MessageUnique.createMsg({ - peerUid: msg.peerUid, - guildId: '', - chatType: msg.chatType, - }, replyMsg.msgId)?.toString(); - //log("找到回复消息", message_data['data']['id'], replyMsg.msgList[0].msgId) - } catch (e: any) { - message_data['type'] = 'unknown' as any; - message_data['data'] = undefined; - logger.logError('获取不到引用的消息', e.stack, element.replyElement.replayMsgSeq); - } + let replyMsgData = await obcore.apiContext.MsgApi.parseReplyElement(msg, element.replyElement); + if (replyMsgData) message_data = replyMsgData; } else if (element.picElement) { - message_data['type'] = OB11MessageDataType.image; - // message_data["data"]["file"] = element.picElement.sourcePath - message_data['data']['file'] = element.picElement.fileName; - message_data['data']['subType'] = element.picElement.picSubType; - message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); - // message_data["data"]["path"] = element.picElement.sourcePath - try { - message_data['data']['url'] = await NTQQFileApi.getImageUrl(element.picElement); - } catch (e: any) { - logger.logError('获取图片url失败', e.stack); - } - //console.log(message_data['data']['url']) - // message_data["data"]["file_id"] = element.picElement.fileUuid - message_data['data']['file_size'] = element.picElement.fileSize; + let PicMsgData = await obcore.apiContext.MsgApi.parsePicElement(msg, element.picElement); + if (PicMsgData) message_data = PicMsgData + ; } else if (element.fileElement) { const FileElement = element.fileElement; message_data['type'] = OB11MessageDataType.file; @@ -256,13 +178,13 @@ export async function RawNTMsg2Onebot( chatType: msg.chatType, guildId: '', }, - msg.msgId, - msg.msgSeq, - msg.senderUid, - element.elementId, - element.elementType.toString(), - element.pttElement.fileSize || '0', - element.pttElement.fileUuid || '' + msg.msgId, + msg.msgSeq, + msg.senderUid, + element.elementId, + element.elementType.toString(), + element.pttElement.fileSize || '0', + element.pttElement.fileUuid || '' ); //以uuid作为文件名 } else if (element.arkElement) { diff --git a/src/onebot/index.ts b/src/onebot/index.ts index c7f34bd4..54f01427 100644 --- a/src/onebot/index.ts +++ b/src/onebot/index.ts @@ -21,7 +21,7 @@ import { OB11PassiveWebSocketAdapter, } from '@/onebot/network'; import { NapCatPathWrapper } from '@/common/framework/napcat'; -import { OneBotFriendApi, OneBotGroupApi, OneBotUserApi } from '@/onebot/api'; +import { OneBotFriendApi, OneBotGroupApi, OneBotMsgApi, OneBotUserApi } from '@/onebot/api'; import { ActionMap, createActionMap } from '@/onebot/action'; import { WebUiDataRuntime } from '@/webui/src/helper/Data'; import { OB11InputStatusEvent } from '@/onebot/event/notice/OB11InputStatusEvent'; @@ -57,6 +57,7 @@ export class NapCatOneBot11Adapter { GroupApi: new OneBotGroupApi(this, core), UserApi: new OneBotUserApi(this, core), FriendApi: new OneBotFriendApi(this, core), + MsgApi: new OneBotMsgApi(this, core), }; this.actions = createActionMap(this, core); this.networkManager = new OB11NetworkManager(); diff --git a/src/onebot/types/adapter.ts b/src/onebot/types/adapter.ts index d4348228..868708c2 100644 --- a/src/onebot/types/adapter.ts +++ b/src/onebot/types/adapter.ts @@ -1,7 +1,8 @@ -import { OneBotFriendApi, OneBotGroupApi, OneBotUserApi } from '../api'; +import { OneBotFriendApi, OneBotGroupApi, OneBotMsgApi, OneBotUserApi } from '../api'; export interface OneBotApiContextType { FriendApi: OneBotFriendApi; UserApi: OneBotUserApi; GroupApi: OneBotGroupApi; + MsgApi: OneBotMsgApi; }