refactor: getFile

This commit is contained in:
手瓜一十雪 2024-08-28 23:27:29 +08:00
parent 7f9da8cc2d
commit 025da8fb76
3 changed files with 83 additions and 59 deletions

View File

@ -1,7 +1,7 @@
import path from 'node:path'; import path from 'node:path';
import fs from 'fs'; import fs from 'fs';
import os from 'node:os'; import os from 'node:os';
import { QQLevel } from '@/core'; import { Peer, QQLevel } from '@/core';
export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ...args: Parameters<T>): Promise<ReturnType<T> | undefined> { export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ...args: Parameters<T>): Promise<ReturnType<T> | undefined> {
return new Promise<ReturnType<T> | undefined>((resolve) => { return new Promise<ReturnType<T> | undefined>((resolve) => {
@ -45,7 +45,29 @@ export class UUIDConverter {
return { high: high.toString(), low: low.toString() }; return { high: high.toString(), low: low.toString() };
} }
} }
export class FileNapCatOneBotUUID {
static encode(peer: Peer, msgId: string, elementId: string): string {
return `NapCatOneBot-File-${peer.chatType}-${peer.peerUid}-${msgId}-${elementId}`;
}
static decode(uuid: string): undefined | {
peer: Peer,
msgId: string,
elementId: string
} {
if (!uuid.startsWith('NapCatOneBot-File-')) return undefined;
const data = uuid.split('-');
if (data.length !== 6) return undefined;
const [, , chatType, peerUid, msgId, elementId] = data;
return {
peer: {
chatType: chatType as any,
peerUid: peerUid
},
msgId,
elementId,
};
}
}
export function sleep(ms: number): Promise<void> { export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms)); return new Promise((resolve) => setTimeout(resolve, ms));
} }

View File

@ -1,8 +1,8 @@
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import fs from 'fs/promises'; import fs from 'fs/promises';
import { UUIDConverter } from '@/common/helper'; import { FileNapCatOneBotUUID } from '@/common/helper';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { ChatType, ElementType, Peer, RawMessage } from '@/core/entities'; import { ChatType, Peer, RawMessage } from '@/core/entities';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
export interface GetFilePayload { export interface GetFilePayload {
@ -29,64 +29,44 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
payloadSchema: any = GetFileBase_PayloadSchema; payloadSchema: any = GetFileBase_PayloadSchema;
async _handle(payload: GetFilePayload): Promise<GetFileResponse> { async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
const NTQQFriendApi = this.core.apis.FriendApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQMsgApi = this.core.apis.MsgApi; const NTQQMsgApi = this.core.apis.MsgApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQFileApi = this.core.apis.FileApi; const NTQQFileApi = this.core.apis.FileApi;
try {
const uuidData = UUIDConverter.decode(payload.file); const contextFile = FileNapCatOneBotUUID.decode(payload.file);
const peerUin = uuidData.high;
const msgId = uuidData.low; //接收消息标记模式
const isGroup: boolean = !!(await NTQQGroupApi.getGroups(false)).find(e => e.groupCode == peerUin); if (contextFile) {
let peer: Peer | undefined; const { peer, msgId, elementId } = contextFile;
//识别Peer
if (isGroup) { const downloadPath = await NTQQFileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', '');
peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: peerUin };
} const mixElement = (await NTQQMsgApi.getMsgsByMsgId(peer, [msgId]))?.msgList
const PeerUid = await NTQQUserApi.getUidByUinV2(peerUin); .find(msg => msg.msgId === msgId)?.elements.find(e => e.elementId === elementId);
if (PeerUid) { const mixElementInner = mixElement?.videoElement ?? mixElement?.fileElement ?? mixElement?.pttElement ?? mixElement?.picElement ;
const isBuddy = await NTQQFriendApi.isBuddy(PeerUid); if(!mixElementInner) throw new Error('element not found');
if (isBuddy) {
peer = { chatType: ChatType.KCHATTYPEC2C, peerUid: PeerUid }; const fileSize = mixElementInner.fileSize?.toString() || '';
} else { const fileName = mixElementInner.fileName || '';
peer = { chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid: PeerUid };
}
}
if (!peer) {
throw new Error('chattype not support');
}
const msgList = await NTQQMsgApi.getMsgsByMsgId(peer, [msgId]);
if (msgList.msgList.length == 0) {
throw new Error('msg not found');
}
const msg = msgList.msgList[0];
const 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');
}
const downloadPath = await NTQQFileApi.downloadMedia(msgId, msg.chatType, msg.peerUid, findEle.elementId, '', '');
const fileSize = findEle?.videoElement?.fileSize || findEle?.fileElement?.fileSize || findEle?.pttElement?.fileSize || '0';
const fileName = findEle?.videoElement?.fileName || findEle?.fileElement?.fileName || findEle?.pttElement?.fileName || '';
const res: GetFileResponse = { const res: GetFileResponse = {
file: downloadPath, file: downloadPath,
url: downloadPath, url: downloadPath,
file_size: fileSize, file_size: fileSize,
file_name: fileName, file_name: fileName,
}; };
if (/* enableLocalFile2Url && */ downloadPath) {
if (this.obContext.configLoader.configData.enableLocalFile2Url && downloadPath) {
try { try {
res.base64 = await fs.readFile(downloadPath, 'base64'); res.base64 = await fs.readFile(downloadPath, 'base64');
} catch (e) { } catch (e) {
throw new Error('文件下载失败. ' + e); throw new Error('文件下载失败. ' + e);
} }
} }
//不手动删除?文件持久化了
return res; return res;
} catch {
this.core.context.logger.logDebug('GetFileBase Mode - 1 Error');
} }
//群文件模式
//搜索名字模式
const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems; const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems;
if (NTSearchNameResult.length !== 0) { if (NTSearchNameResult.length !== 0) {
const MsgId = NTSearchNameResult[0].msgId; const MsgId = NTSearchNameResult[0].msgId;
@ -94,9 +74,7 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
if (NTSearchNameResult[0].chatType == ChatType.KCHATTYPEGROUP) { if (NTSearchNameResult[0].chatType == ChatType.KCHATTYPEGROUP) {
peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: NTSearchNameResult[0].groupChatInfo[0].groupCode }; peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: NTSearchNameResult[0].groupChatInfo[0].groupCode };
} }
if (!peer) { if (!peer) throw new Error('chattype not support');
throw new Error('chattype not support');
}
const msgList: RawMessage[] = (await NTQQMsgApi.getMsgsByMsgId(peer, [MsgId]))?.msgList; const msgList: RawMessage[] = (await NTQQMsgApi.getMsgsByMsgId(peer, [MsgId]))?.msgList;
if (!msgList || msgList.length == 0) { if (!msgList || msgList.length == 0) {
throw new Error('msg not found'); throw new Error('msg not found');
@ -113,16 +91,16 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
file_size: NTSearchNameResult[0].fileSize.toString(), file_size: NTSearchNameResult[0].fileSize.toString(),
file_name: NTSearchNameResult[0].fileName, file_name: NTSearchNameResult[0].fileName,
}; };
if (/* enableLocalFile2Url && */ downloadPath) { if (this.obContext.configLoader.configData.enableLocalFile2Url && downloadPath) {
try { try {
res.base64 = await fs.readFile(downloadPath, 'base64'); res.base64 = await fs.readFile(downloadPath, 'base64');
} catch (e) { } catch (e) {
throw new Error('文件下载失败. ' + e); throw new Error('文件下载失败. ' + e);
} }
} }
//不手动删除?文件持久化了
return res; return res;
} }
throw new Error('file not found'); throw new Error('file not found');
} }
} }

View File

@ -1,4 +1,4 @@
import { UUIDConverter } from '@/common/helper'; import { FileNapCatOneBotUUID } from '@/common/helper';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { import {
AtType, AtType,
@ -98,14 +98,19 @@ export class OneBotMsgApi {
} }
}, },
picElement: async (element, msg) => { picElement: async (element, msg, elementWrapper) => {
try { try {
const peer = {
chatType: msg.chatType,
peerUid: msg.peerUid,
guildId: '',
};
return { return {
type: OB11MessageDataType.image, type: OB11MessageDataType.image,
data: { data: {
file: element.fileName, file: element.fileName,
sub_type: element.picSubType, sub_type: element.picSubType,
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId), file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
url: await this.core.apis.FileApi.getImageUrl(element), url: await this.core.apis.FileApi.getImageUrl(element),
file_size: element.fileSize, file_size: element.fileSize,
}, },
@ -117,6 +122,11 @@ export class OneBotMsgApi {
}, },
fileElement: async (element, msg, elementWrapper) => { fileElement: async (element, msg, elementWrapper) => {
const peer = {
chatType: msg.chatType,
peerUid: msg.peerUid,
guildId: '',
};
await this.core.apis.FileApi.addFileCache( await this.core.apis.FileApi.addFileCache(
{ {
peerUid: msg.peerUid, peerUid: msg.peerUid,
@ -137,7 +147,7 @@ export class OneBotMsgApi {
file: element.fileName, file: element.fileName,
path: element.filePath, path: element.filePath,
url: element.filePath, url: element.filePath,
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId), file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
file_size: element.fileSize, file_size: element.fileSize,
}, },
}; };
@ -184,11 +194,16 @@ export class OneBotMsgApi {
'0', '0',
'marketface', 'marketface',
); );
const peer = {
chatType: msg.chatType,
peerUid: msg.peerUid,
guildId: '',
};
return { return {
type: OB11MessageDataType.image, type: OB11MessageDataType.image,
data: { data: {
file: 'marketface', file: 'marketface',
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId), file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
path: elementWrapper.elementId, path: elementWrapper.elementId,
url: elementWrapper.elementId, url: elementWrapper.elementId,
}, },
@ -247,7 +262,11 @@ export class OneBotMsgApi {
videoElement: async (element, msg, elementWrapper) => { videoElement: async (element, msg, elementWrapper) => {
const NTQQFileApi = this.core.apis.FileApi; const NTQQFileApi = this.core.apis.FileApi;
const peer = {
chatType: msg.chatType,
peerUid: msg.peerUid,
guildId: '',
};
//读取视频链接并兜底 //读取视频链接并兜底
let videoUrlWrappers: Awaited<ReturnType<typeof NTQQFileApi.getVideoUrl>> | undefined; let videoUrlWrappers: Awaited<ReturnType<typeof NTQQFileApi.getVideoUrl>> | undefined;
@ -302,13 +321,18 @@ export class OneBotMsgApi {
file: element.fileName, file: element.fileName,
path: videoDownUrl, path: videoDownUrl,
url: videoDownUrl, url: videoDownUrl,
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId), file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
file_size: element.fileSize, file_size: element.fileSize,
}, },
}; };
}, },
pttElement: async (element, msg, elementWrapper) => { pttElement: async (element, msg, elementWrapper) => {
const peer = {
chatType: msg.chatType,
peerUid: msg.peerUid,
guildId: '',
};
await this.core.apis.FileApi.addFileCache( await this.core.apis.FileApi.addFileCache(
{ {
peerUid: msg.peerUid, peerUid: msg.peerUid,
@ -328,7 +352,7 @@ export class OneBotMsgApi {
data: { data: {
file: element.fileName, file: element.fileName,
path: element.filePath, path: element.filePath,
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId), file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
file_size: element.fileSize, file_size: element.fileSize,
}, },
}; };