diff --git a/src/common/utils/helper.ts b/src/common/utils/helper.ts index 63273770..eb87462f 100644 --- a/src/common/utils/helper.ts +++ b/src/common/utils/helper.ts @@ -8,6 +8,27 @@ import * as fsPromise from 'node:fs/promises'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); + +//下面这个类是用于将uid+msgid合并的类 +export class UUIDConverter { + static encode(highStr: string, lowStr: string): string { + const high = BigInt(highStr); + const low = BigInt(lowStr); + const highHex = high.toString(16).padStart(16, '0'); + const lowHex = low.toString(16).padStart(16, '0'); + const combinedHex = highHex + lowHex; + const uuid = `${combinedHex.substring(0, 8)}-${combinedHex.substring(8, 12)}-${combinedHex.substring(12, 16)}-${combinedHex.substring(16, 20)}-${combinedHex.substring(20)}`; + return uuid; + } + static decode(uuid: string): { high: string, low: string } { + const hex = uuid.replace(/-/g, ''); + const high = BigInt('0x' + hex.substring(0, 16)); + const low = BigInt('0x' + hex.substring(16)); + return { high: high.toString(), low: low.toString() }; + } +} + + export function sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/src/core/src/apis/file.ts b/src/core/src/apis/file.ts index f922a7c0..4564d4da 100644 --- a/src/core/src/apis/file.ts +++ b/src/core/src/apis/file.ts @@ -18,6 +18,7 @@ import { sessionConfig } from '@/core/sessionConfig'; import { rkeyManager } from '../utils/rkey'; import { NTEventDispatch } from '@/common/utils/EventTask'; import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService'; +import { selfInfo } from '../data'; export class NTQQFileApi { @@ -67,7 +68,9 @@ export class NTQQFileApi { ext }; } - + static async downloadMediaByUuid() { + //napCatCore.session.getRichMediaService().downloadFileForFileUuid(); + } static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) { //logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force); // 用于下载收到的消息中的图片等 diff --git a/src/onebot11/action/file/GetFile.ts b/src/onebot11/action/file/GetFile.ts index 5a866bbc..1c9363ad 100644 --- a/src/onebot11/action/file/GetFile.ts +++ b/src/onebot11/action/file/GetFile.ts @@ -1,15 +1,12 @@ import BaseAction from '../BaseAction'; import fs from 'fs/promises'; import { ob11Config } from '@/onebot11/config'; -import { log, logDebug } from '@/common/utils/log'; -import { sleep } from '@/common/utils/helper'; -import { uri2local } from '@/common/utils/file'; +import { UUIDConverter } from '@/common/utils/helper'; import { ActionName, BaseCheckResult } from '../types'; -import { ChatType, FileElement, Peer, RawMessage, VideoElement } from '@/core/entities'; -import { NTQQFileApi, NTQQMsgApi } from '@/core/apis'; +import { ChatType, ElementType, FileElement, Peer, RawMessage, VideoElement } from '@/core/entities'; +import { NTQQFileApi, NTQQFriendApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis'; import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import Ajv from 'ajv'; -import { MessageUnique } from '@/common/utils/MessageUnique'; +import { getGroup } from '@/core/data'; export interface GetFilePayload { file: string; // 文件名或者fileUuid @@ -46,6 +43,65 @@ export class GetFileBase extends BaseAction { } protected async _handle(payload: GetFilePayload): Promise { const { enableLocalFile2Url } = ob11Config; + let UuidData: { + high: string; + low: string; + } | undefined; + try { + UuidData = UUIDConverter.decode(payload.file); + if (UuidData) { + let peerUin = UuidData.high; + let msgId = UuidData.low; + let isGroup = await getGroup(peerUin); + let peer: Peer | undefined; + //识别Peer + if (isGroup) { + peer = { chatType: ChatType.group, peerUid: peerUin }; + } + let PeerUid = await NTQQUserApi.getUidByUin(peerUin); + if (PeerUid) { + let isBuddy = await NTQQFriendApi.isBuddy(PeerUid); + if (isBuddy) { + peer = { chatType: ChatType.friend, peerUid: PeerUid }; + } else { + peer = { chatType: ChatType.temp, peerUid: PeerUid }; + } + } + if (!peer) { + throw new Error('chattype not support'); + } + let msgList = await NTQQMsgApi.getMsgsByMsgId(peer, [msgId]); + if (msgList.msgList.length == 0) { + throw new Error('msg not found'); + } + let msg = msgList.msgList[0]; + let findEle = msg.elements.find(e => e.elementType == ElementType.VIDEO || e.elementType == ElementType.FILE || e.elementType == ElementType.PTT); + if (!findEle) { + throw new Error('element not found'); + } + let downloadPath = await NTQQFileApi.downloadMedia(msgId, msg.chatType, msg.peerUid, findEle.elementId, '', ''); + let fileSize = findEle?.videoElement?.fileSize || findEle?.fileElement?.fileSize || findEle?.pttElement?.fileSize || '0'; + let fileName = findEle?.videoElement?.fileName || findEle?.fileElement?.fileName || findEle?.pttElement?.fileName || ''; + const res: GetFileResponse = { + file: downloadPath, + url: downloadPath, + file_size: fileSize, + file_name: fileName + }; + if (enableLocalFile2Url) { + try { + res.base64 = await fs.readFile(downloadPath, 'base64'); + } catch (e) { + throw new Error('文件下载失败. ' + e); + } + } + //不手动删除?文件持久化了 + return res; + } + } catch { + + } + const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems; if (NTSearchNameResult.length !== 0) { const MsgId = NTSearchNameResult[0].msgId; @@ -69,7 +125,7 @@ export class GetFileBase extends BaseAction { const res: GetFileResponse = { file: downloadPath, url: downloadPath, - file_size: NTSearchNameResult[0].fileSize.toString(), + file_size: NTSearchNameResult[0].fileSize.toString(), file_name: NTSearchNameResult[0].fileName }; if (enableLocalFile2Url) { @@ -82,7 +138,6 @@ export class GetFileBase extends BaseAction { //不手动删除?文件持久化了 return res; } - //下面逻辑是有UUID的情况 throw new Error('file not found'); // let cache = await dbUtil.getFileCacheByName(payload.file); // if (!cache) { diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index c2565cf8..e4eb0bac 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -35,7 +35,7 @@ import { OB11GroupNoticeEvent } from './event/notice/OB11GroupNoticeEvent'; import { calcQQLevel } from '../common/utils/qqlevel'; import { log, logDebug, logError, logWarn } from '../common/utils/log'; -import { sleep } from '../common/utils/helper'; +import { sleep, UUIDConverter } from '../common/utils/helper'; import { OB11GroupTitleEvent } from './event/notice/OB11GroupTitleEvent'; import { OB11GroupCardEvent } from './event/notice/OB11GroupCardEvent'; import { OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent'; @@ -185,13 +185,12 @@ export class OB11Constructor { message_data['data']['file_size'] = element.picElement.fileSize; } else if (element.fileElement) { - const FileElement = element.fileElement; message_data['type'] = OB11MessageDataType.file; message_data['data']['file'] = FileElement.fileName; message_data['data']['path'] = FileElement.filePath; message_data['data']['url'] = FileElement.filePath; - message_data['data']['file_id'] = FileElement.fileUuid; + message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); message_data['data']['file_size'] = FileElement.fileSize; await NTQQFileApi.addFileCache({ peerUid: msg.peerUid, @@ -237,7 +236,7 @@ export class OB11Constructor { message_data['data']['file'] = videoElement.fileName; message_data['data']['path'] = videoDownUrl; message_data['data']['url'] = videoDownUrl; - message_data['data']['file_id'] = videoElement.fileUuid; + message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); message_data['data']['file_size'] = videoElement.fileSize; await NTQQFileApi.addFileCache({ @@ -258,19 +257,9 @@ export class OB11Constructor { message_data['type'] = OB11MessageDataType.voice; message_data['data']['file'] = element.pttElement.fileName; message_data['data']['path'] = element.pttElement.filePath; - message_data['data']['file_id'] = element.pttElement.fileUuid; + //message_data['data']['file_id'] = element.pttElement.fileUuid; + message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId); message_data['data']['file_size'] = element.pttElement.fileSize; - // dbUtil.addFileCache({ - // name: element.pttElement.fileName, - // path: element.pttElement.filePath, - // size: parseInt(element.pttElement.fileSize) || 0, - // url: '', - // uuid: element.pttElement.fileUuid || '', - // msgId: msg.msgId, - // element: element.pttElement, - // elementType: ElementType.PTT, - // elementId: element.elementId - // }).then(); await NTQQFileApi.addFileCache({ peerUid: msg.peerUid, chatType: msg.chatType, @@ -350,6 +339,7 @@ export class OB11Constructor { if (element.grayTipElement) { if (element.grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) { const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr); + if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) { //判断业务类型 //Poke事件 @@ -358,7 +348,7 @@ export class OB11Constructor { pokedetail = pokedetail.filter(item => item.uid); //console.log("[NapCat] 群拍一拍 群:", pokedetail, parseInt(msg.peerUid), " ", await NTQQUserApi.getUinByUid(pokedetail[0].uid), "拍了拍", await NTQQUserApi.getUinByUid(pokedetail[1].uid)); if (pokedetail.length == 2) { - return new OB11FriendPokeEvent(parseInt((await NTQQUserApi.getUinByUid(pokedetail[0].uid))!), parseInt((await NTQQUserApi.getUinByUid(pokedetail[1].uid))!)); + return new OB11FriendPokeEvent(parseInt((await NTQQUserApi.getUinByUid(pokedetail[0].uid))!), parseInt((await NTQQUserApi.getUinByUid(pokedetail[1].uid))!), pokedetail); } } //下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE