mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
refactor: getfile
This commit is contained in:
@@ -8,6 +8,27 @@ import * as fsPromise from 'node:fs/promises';
|
|||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = dirname(__filename);
|
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<void> {
|
export function sleep(ms: number): Promise<void> {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@ import { sessionConfig } from '@/core/sessionConfig';
|
|||||||
import { rkeyManager } from '../utils/rkey';
|
import { rkeyManager } from '../utils/rkey';
|
||||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||||
import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService';
|
import { NodeIKernelSearchService } from '../services/NodeIKernelSearchService';
|
||||||
|
import { selfInfo } from '../data';
|
||||||
|
|
||||||
|
|
||||||
export class NTQQFileApi {
|
export class NTQQFileApi {
|
||||||
@@ -67,7 +68,9 @@ export class NTQQFileApi {
|
|||||||
ext
|
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) {
|
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);
|
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
||||||
// 用于下载收到的消息中的图片等
|
// 用于下载收到的消息中的图片等
|
||||||
|
@@ -1,15 +1,12 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import { ob11Config } from '@/onebot11/config';
|
import { ob11Config } from '@/onebot11/config';
|
||||||
import { log, logDebug } from '@/common/utils/log';
|
import { UUIDConverter } from '@/common/utils/helper';
|
||||||
import { sleep } from '@/common/utils/helper';
|
|
||||||
import { uri2local } from '@/common/utils/file';
|
|
||||||
import { ActionName, BaseCheckResult } from '../types';
|
import { ActionName, BaseCheckResult } from '../types';
|
||||||
import { ChatType, FileElement, Peer, RawMessage, VideoElement } from '@/core/entities';
|
import { ChatType, ElementType, FileElement, Peer, RawMessage, VideoElement } from '@/core/entities';
|
||||||
import { NTQQFileApi, NTQQMsgApi } from '@/core/apis';
|
import { NTQQFileApi, NTQQFriendApi, NTQQMsgApi, NTQQUserApi } from '@/core/apis';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import Ajv from 'ajv';
|
import { getGroup } from '@/core/data';
|
||||||
import { MessageUnique } from '@/common/utils/MessageUnique';
|
|
||||||
|
|
||||||
export interface GetFilePayload {
|
export interface GetFilePayload {
|
||||||
file: string; // 文件名或者fileUuid
|
file: string; // 文件名或者fileUuid
|
||||||
@@ -46,6 +43,65 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
}
|
}
|
||||||
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
||||||
const { enableLocalFile2Url } = ob11Config;
|
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;
|
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;
|
||||||
@@ -69,7 +125,7 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
const res: GetFileResponse = {
|
const res: GetFileResponse = {
|
||||||
file: downloadPath,
|
file: downloadPath,
|
||||||
url: downloadPath,
|
url: downloadPath,
|
||||||
file_size: NTSearchNameResult[0].fileSize.toString(),
|
file_size: NTSearchNameResult[0].fileSize.toString(),
|
||||||
file_name: NTSearchNameResult[0].fileName
|
file_name: NTSearchNameResult[0].fileName
|
||||||
};
|
};
|
||||||
if (enableLocalFile2Url) {
|
if (enableLocalFile2Url) {
|
||||||
@@ -82,7 +138,6 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
//不手动删除?文件持久化了
|
//不手动删除?文件持久化了
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
//下面逻辑是有UUID的情况
|
|
||||||
throw new Error('file not found');
|
throw new Error('file not found');
|
||||||
// let cache = await dbUtil.getFileCacheByName(payload.file);
|
// let cache = await dbUtil.getFileCacheByName(payload.file);
|
||||||
// if (!cache) {
|
// if (!cache) {
|
||||||
|
@@ -35,7 +35,7 @@ import { OB11GroupNoticeEvent } from './event/notice/OB11GroupNoticeEvent';
|
|||||||
|
|
||||||
import { calcQQLevel } from '../common/utils/qqlevel';
|
import { calcQQLevel } from '../common/utils/qqlevel';
|
||||||
import { log, logDebug, logError, logWarn } from '../common/utils/log';
|
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 { OB11GroupTitleEvent } from './event/notice/OB11GroupTitleEvent';
|
||||||
import { OB11GroupCardEvent } from './event/notice/OB11GroupCardEvent';
|
import { OB11GroupCardEvent } from './event/notice/OB11GroupCardEvent';
|
||||||
import { OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent';
|
import { OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent';
|
||||||
@@ -185,13 +185,12 @@ export class OB11Constructor {
|
|||||||
message_data['data']['file_size'] = element.picElement.fileSize;
|
message_data['data']['file_size'] = element.picElement.fileSize;
|
||||||
}
|
}
|
||||||
else if (element.fileElement) {
|
else if (element.fileElement) {
|
||||||
|
|
||||||
const FileElement = element.fileElement;
|
const FileElement = element.fileElement;
|
||||||
message_data['type'] = OB11MessageDataType.file;
|
message_data['type'] = OB11MessageDataType.file;
|
||||||
message_data['data']['file'] = FileElement.fileName;
|
message_data['data']['file'] = FileElement.fileName;
|
||||||
message_data['data']['path'] = FileElement.filePath;
|
message_data['data']['path'] = FileElement.filePath;
|
||||||
message_data['data']['url'] = 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;
|
message_data['data']['file_size'] = FileElement.fileSize;
|
||||||
await NTQQFileApi.addFileCache({
|
await NTQQFileApi.addFileCache({
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
@@ -237,7 +236,7 @@ export class OB11Constructor {
|
|||||||
message_data['data']['file'] = videoElement.fileName;
|
message_data['data']['file'] = videoElement.fileName;
|
||||||
message_data['data']['path'] = videoDownUrl;
|
message_data['data']['path'] = videoDownUrl;
|
||||||
message_data['data']['url'] = 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;
|
message_data['data']['file_size'] = videoElement.fileSize;
|
||||||
|
|
||||||
await NTQQFileApi.addFileCache({
|
await NTQQFileApi.addFileCache({
|
||||||
@@ -258,19 +257,9 @@ export class OB11Constructor {
|
|||||||
message_data['type'] = OB11MessageDataType.voice;
|
message_data['type'] = OB11MessageDataType.voice;
|
||||||
message_data['data']['file'] = element.pttElement.fileName;
|
message_data['data']['file'] = element.pttElement.fileName;
|
||||||
message_data['data']['path'] = element.pttElement.filePath;
|
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;
|
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({
|
await NTQQFileApi.addFileCache({
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
chatType: msg.chatType,
|
chatType: msg.chatType,
|
||||||
@@ -350,6 +339,7 @@ export class OB11Constructor {
|
|||||||
if (element.grayTipElement) {
|
if (element.grayTipElement) {
|
||||||
if (element.grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) {
|
if (element.grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) {
|
||||||
const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr);
|
const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr);
|
||||||
|
|
||||||
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
||||||
//判断业务类型
|
//判断业务类型
|
||||||
//Poke事件
|
//Poke事件
|
||||||
@@ -358,7 +348,7 @@ export class OB11Constructor {
|
|||||||
pokedetail = pokedetail.filter(item => item.uid);
|
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));
|
//console.log("[NapCat] 群拍一拍 群:", pokedetail, parseInt(msg.peerUid), " ", await NTQQUserApi.getUinByUid(pokedetail[0].uid), "拍了拍", await NTQQUserApi.getUinByUid(pokedetail[1].uid));
|
||||||
if (pokedetail.length == 2) {
|
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
|
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
|
||||||
|
Reference in New Issue
Block a user