mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
feat: file cache db
This commit is contained in:
parent
62eefbdb69
commit
0480208738
@ -28,8 +28,6 @@ export const llonebotError: LLOneBotError = {
|
|||||||
otherError: ''
|
otherError: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fileCache = new Map<string, FileCache>()
|
|
||||||
|
|
||||||
|
|
||||||
export async function getFriend(qq: string, uid: string = ""): Promise<Friend | undefined> {
|
export async function getFriend(qq: string, uid: string = ""): Promise<Friend | undefined> {
|
||||||
let filterKey = uid ? "uid" : "uin"
|
let filterKey = uid ? "uid" : "uin"
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
// import {DATA_DIR} from "./utils";
|
|
||||||
import {Level} from "level";
|
import {Level} from "level";
|
||||||
import {RawMessage} from "../ntqqapi/types";
|
import {RawMessage} from "../ntqqapi/types";
|
||||||
import {DATA_DIR, log} from "./utils";
|
import {DATA_DIR, log} from "./utils";
|
||||||
import {selfInfo} from "./data";
|
import {selfInfo} from "./data";
|
||||||
import * as wasi from "wasi";
|
import {FileCache} from "./types";
|
||||||
|
|
||||||
|
|
||||||
class DBUtil {
|
class DBUtil {
|
||||||
private readonly DB_KEY_PREFIX_MSG_ID = "msg_id_";
|
private readonly DB_KEY_PREFIX_MSG_ID = "msg_id_";
|
||||||
private readonly DB_KEY_PREFIX_MSG_SHORT_ID = "msg_short_id_";
|
private readonly DB_KEY_PREFIX_MSG_SHORT_ID = "msg_short_id_";
|
||||||
private readonly DB_KEY_PREFIX_MSG_SEQ_ID = "msg_seq_id_";
|
private readonly DB_KEY_PREFIX_MSG_SEQ_ID = "msg_seq_id_";
|
||||||
|
private readonly DB_KEY_PREFIX_FILE = "file_";
|
||||||
private db: Level;
|
private db: Level;
|
||||||
private cache: Record<string, RawMessage> = {} // <msg_id_ | msg_short_id_ | msg_seq_id_><id>: RawMessage
|
private cache: Record<string, RawMessage | string | FileCache> = {} // <msg_id_ | msg_short_id_ | msg_seq_id_><id>: RawMessage
|
||||||
private currentShortId: number;
|
private currentShortId: number;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -19,6 +19,7 @@ class DBUtil {
|
|||||||
* msg_id_101231230999: {} // 长id: RawMessage
|
* msg_id_101231230999: {} // 长id: RawMessage
|
||||||
* msg_short_id_1: 101231230999 // 短id: 长id
|
* msg_short_id_1: 101231230999 // 短id: 长id
|
||||||
* msg_seq_id_1: 101231230999 // 序列id: 长id
|
* msg_seq_id_1: 101231230999 // 序列id: 长id
|
||||||
|
* file_7827DBAFJFW2323.png: {} // 文件名: FileCache
|
||||||
* */
|
* */
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -61,7 +62,7 @@ class DBUtil {
|
|||||||
async getMsgByShortId(shortMsgId: number): Promise<RawMessage> {
|
async getMsgByShortId(shortMsgId: number): Promise<RawMessage> {
|
||||||
const shortMsgIdKey = this.DB_KEY_PREFIX_MSG_SHORT_ID + shortMsgId;
|
const shortMsgIdKey = this.DB_KEY_PREFIX_MSG_SHORT_ID + shortMsgId;
|
||||||
if (this.cache[shortMsgIdKey]) {
|
if (this.cache[shortMsgIdKey]) {
|
||||||
return this.cache[shortMsgIdKey]
|
return this.cache[shortMsgIdKey] as RawMessage
|
||||||
}
|
}
|
||||||
const longId = await this.db.get(shortMsgIdKey);
|
const longId = await this.db.get(shortMsgIdKey);
|
||||||
const msg = await this.getMsgByLongId(longId)
|
const msg = await this.getMsgByLongId(longId)
|
||||||
@ -72,7 +73,7 @@ class DBUtil {
|
|||||||
async getMsgByLongId(longId: string): Promise<RawMessage> {
|
async getMsgByLongId(longId: string): Promise<RawMessage> {
|
||||||
const longIdKey = this.DB_KEY_PREFIX_MSG_ID + longId;
|
const longIdKey = this.DB_KEY_PREFIX_MSG_ID + longId;
|
||||||
if (this.cache[longIdKey]) {
|
if (this.cache[longIdKey]) {
|
||||||
return this.cache[longIdKey]
|
return this.cache[longIdKey] as RawMessage
|
||||||
}
|
}
|
||||||
const data = await this.db.get(longIdKey)
|
const data = await this.db.get(longIdKey)
|
||||||
const msg = JSON.parse(data)
|
const msg = JSON.parse(data)
|
||||||
@ -83,7 +84,7 @@ class DBUtil {
|
|||||||
async getMsgBySeqId(seqId: string): Promise<RawMessage> {
|
async getMsgBySeqId(seqId: string): Promise<RawMessage> {
|
||||||
const seqIdKey = this.DB_KEY_PREFIX_MSG_SEQ_ID + seqId;
|
const seqIdKey = this.DB_KEY_PREFIX_MSG_SEQ_ID + seqId;
|
||||||
if (this.cache[seqIdKey]) {
|
if (this.cache[seqIdKey]) {
|
||||||
return this.cache[seqIdKey]
|
return this.cache[seqIdKey] as RawMessage
|
||||||
}
|
}
|
||||||
const longId = await this.db.get(seqIdKey);
|
const longId = await this.db.get(seqIdKey);
|
||||||
const msg = await this.getMsgByLongId(longId)
|
const msg = await this.getMsgByLongId(longId)
|
||||||
@ -95,7 +96,7 @@ class DBUtil {
|
|||||||
// 有则更新,无则添加
|
// 有则更新,无则添加
|
||||||
// log("addMsg", msg.msgId, msg.msgSeq, msg.msgShortId);
|
// log("addMsg", msg.msgId, msg.msgSeq, msg.msgShortId);
|
||||||
const longIdKey = this.DB_KEY_PREFIX_MSG_ID + msg.msgId
|
const longIdKey = this.DB_KEY_PREFIX_MSG_ID + msg.msgId
|
||||||
let existMsg = this.cache[longIdKey]
|
let existMsg = this.cache[longIdKey] as RawMessage
|
||||||
if (!existMsg) {
|
if (!existMsg) {
|
||||||
try {
|
try {
|
||||||
existMsg = await this.getMsgByLongId(msg.msgId)
|
existMsg = await this.getMsgByLongId(msg.msgId)
|
||||||
@ -136,7 +137,7 @@ class DBUtil {
|
|||||||
|
|
||||||
async updateMsg(msg: RawMessage) {
|
async updateMsg(msg: RawMessage) {
|
||||||
const longIdKey = this.DB_KEY_PREFIX_MSG_ID + msg.msgId
|
const longIdKey = this.DB_KEY_PREFIX_MSG_ID + msg.msgId
|
||||||
let existMsg = this.cache[longIdKey]
|
let existMsg = this.cache[longIdKey] as RawMessage
|
||||||
if (!existMsg) {
|
if (!existMsg) {
|
||||||
try {
|
try {
|
||||||
existMsg = await this.getMsgByLongId(msg.msgId)
|
existMsg = await this.getMsgByLongId(msg.msgId)
|
||||||
@ -179,6 +180,31 @@ class DBUtil {
|
|||||||
await this.db.put(key, this.currentShortId.toString());
|
await this.db.put(key, this.currentShortId.toString());
|
||||||
return this.currentShortId;
|
return this.currentShortId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addFileCache(fileName: string, data: FileCache) {
|
||||||
|
const key = this.DB_KEY_PREFIX_FILE + fileName;
|
||||||
|
if (this.cache[key]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let cacheDBData = {...data}
|
||||||
|
delete cacheDBData['downloadFunc']
|
||||||
|
this.cache[fileName] = data;
|
||||||
|
await this.db.put(key, JSON.stringify(cacheDBData));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFileCache(fileName: string): Promise<FileCache | undefined> {
|
||||||
|
const key = this.DB_KEY_PREFIX_FILE + fileName;
|
||||||
|
if (this.cache[key]) {
|
||||||
|
return this.cache[key] as FileCache
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
|
||||||
|
let data = await this.db.get(key);
|
||||||
|
return JSON.parse(data);
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const dbUtil = new DBUtil();
|
export const dbUtil = new DBUtil();
|
@ -1,7 +1,7 @@
|
|||||||
import BaseAction from "./BaseAction";
|
import BaseAction from "./BaseAction";
|
||||||
import {fileCache} from "../../common/data";
|
|
||||||
import {getConfigUtil} from "../../common/utils";
|
import {getConfigUtil} from "../../common/utils";
|
||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
|
import {dbUtil} from "../../common/db";
|
||||||
|
|
||||||
export interface GetFilePayload {
|
export interface GetFilePayload {
|
||||||
file: string // 文件名
|
file: string // 文件名
|
||||||
@ -18,7 +18,7 @@ export interface GetFileResponse {
|
|||||||
|
|
||||||
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
||||||
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
||||||
const cache = fileCache.get(payload.file)
|
const cache = await dbUtil.getFileCache(payload.file)
|
||||||
const {autoDeleteFile, enableLocalFile2Url, autoDeleteFileSecond} = getConfigUtil().getConfig()
|
const {autoDeleteFile, enableLocalFile2Url, autoDeleteFileSecond} = getConfigUtil().getConfig()
|
||||||
if (!cache) {
|
if (!cache) {
|
||||||
throw new Error('file not found')
|
throw new Error('file not found')
|
||||||
|
@ -18,6 +18,7 @@ import {log} from "../../common/utils";
|
|||||||
import {decodeCQCode} from "../cqcode";
|
import {decodeCQCode} from "../cqcode";
|
||||||
import {dbUtil} from "../../common/db";
|
import {dbUtil} from "../../common/db";
|
||||||
import {ALLOW_SEND_TEMP_MSG} from "../../common/config";
|
import {ALLOW_SEND_TEMP_MSG} from "../../common/config";
|
||||||
|
import {FileCache} from "../../common/types";
|
||||||
|
|
||||||
function checkSendMessage(sendMsgList: OB11MessageData[]) {
|
function checkSendMessage(sendMsgList: OB11MessageData[]) {
|
||||||
function checkUri(uri: string): boolean {
|
function checkUri(uri: string): boolean {
|
||||||
@ -328,9 +329,20 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
case OB11MessageDataType.file:
|
case OB11MessageDataType.file:
|
||||||
case OB11MessageDataType.video:
|
case OB11MessageDataType.video:
|
||||||
case OB11MessageDataType.voice: {
|
case OB11MessageDataType.voice: {
|
||||||
const file = sendMsg.data?.file
|
let file = sendMsg.data?.file
|
||||||
const payloadFileName = sendMsg.data?.name
|
const payloadFileName = sendMsg.data?.name
|
||||||
if (file) {
|
if (file) {
|
||||||
|
const cache = await dbUtil.getFileCache(file)
|
||||||
|
if (cache){
|
||||||
|
if (fs.existsSync(cache.filePath)){
|
||||||
|
file = "file://" + cache.filePath
|
||||||
|
}
|
||||||
|
else if (cache.downloadFunc){
|
||||||
|
await cache.downloadFunc()
|
||||||
|
file = cache.filePath;
|
||||||
|
log("找到文件缓存", file);
|
||||||
|
}
|
||||||
|
}
|
||||||
const {path, isLocal, fileName, errMsg} = (await uri2local(file))
|
const {path, isLocal, fileName, errMsg} = (await uri2local(file))
|
||||||
if (errMsg){
|
if (errMsg){
|
||||||
throw errMsg
|
throw errMsg
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
OB11UserSex
|
OB11UserSex
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import {AtType, ChatType, Group, GroupMember, IMAGE_HTTP_HOST, RawMessage, SelfInfo, User} from '../ntqqapi/types';
|
import {AtType, ChatType, Group, GroupMember, IMAGE_HTTP_HOST, RawMessage, SelfInfo, User} from '../ntqqapi/types';
|
||||||
import {fileCache, getFriend, getGroupMember, selfInfo, tempGroupCodeMap} from '../common/data';
|
import {getFriend, getGroupMember, selfInfo, tempGroupCodeMap} from '../common/data';
|
||||||
import {getConfigUtil, log} from "../common/utils";
|
import {getConfigUtil, log} from "../common/utils";
|
||||||
import {NTQQApi} from "../ntqqapi/ntcall";
|
import {NTQQApi} from "../ntqqapi/ntcall";
|
||||||
import {EventType} from "./event/OB11BaseEvent";
|
import {EventType} from "./event/OB11BaseEvent";
|
||||||
@ -120,11 +120,11 @@ export class OB11Constructor {
|
|||||||
message_data["data"]["url"] = IMAGE_HTTP_HOST + url
|
message_data["data"]["url"] = IMAGE_HTTP_HOST + url
|
||||||
}
|
}
|
||||||
else if (fileMd5){
|
else if (fileMd5){
|
||||||
message_data["data"]["file_id"] = `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${fileMd5}/0`
|
message_data["data"]["file_id"] = `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${fileMd5.toUpperCase()}/0`
|
||||||
}
|
}
|
||||||
// message_data["data"]["file_id"] = element.picElement.fileUuid
|
// message_data["data"]["file_id"] = element.picElement.fileUuid
|
||||||
message_data["data"]["file_size"] = element.picElement.fileSize
|
message_data["data"]["file_size"] = element.picElement.fileSize
|
||||||
fileCache.set(element.picElement.fileName, {
|
dbUtil.addFileCache(element.picElement.fileName, {
|
||||||
fileName: element.picElement.fileName,
|
fileName: element.picElement.fileName,
|
||||||
filePath: element.picElement.sourcePath,
|
filePath: element.picElement.sourcePath,
|
||||||
fileSize: element.picElement.fileSize.toString(),
|
fileSize: element.picElement.fileSize.toString(),
|
||||||
@ -133,7 +133,7 @@ export class OB11Constructor {
|
|||||||
await NTQQApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
await NTQQApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
||||||
element.elementId, element.picElement.thumbPath?.get(0) || "", element.picElement.sourcePath)
|
element.elementId, element.picElement.thumbPath?.get(0) || "", element.picElement.sourcePath)
|
||||||
}
|
}
|
||||||
})
|
}).then()
|
||||||
// 不在自动下载图片
|
// 不在自动下载图片
|
||||||
|
|
||||||
} else if (element.videoElement) {
|
} else if (element.videoElement) {
|
||||||
@ -142,7 +142,7 @@ export class OB11Constructor {
|
|||||||
message_data["data"]["path"] = element.videoElement.filePath
|
message_data["data"]["path"] = element.videoElement.filePath
|
||||||
// message_data["data"]["file_id"] = element.videoElement.fileUuid
|
// message_data["data"]["file_id"] = element.videoElement.fileUuid
|
||||||
message_data["data"]["file_size"] = element.videoElement.fileSize
|
message_data["data"]["file_size"] = element.videoElement.fileSize
|
||||||
fileCache.set(element.videoElement.fileName, {
|
dbUtil.addFileCache(element.videoElement.fileName, {
|
||||||
fileName: element.videoElement.fileName,
|
fileName: element.videoElement.fileName,
|
||||||
filePath: element.videoElement.filePath,
|
filePath: element.videoElement.filePath,
|
||||||
fileSize: element.videoElement.fileSize,
|
fileSize: element.videoElement.fileSize,
|
||||||
@ -150,7 +150,7 @@ export class OB11Constructor {
|
|||||||
await NTQQApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
await NTQQApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
||||||
element.elementId, element.videoElement.thumbPath.get(0), element.videoElement.filePath)
|
element.elementId, element.videoElement.thumbPath.get(0), element.videoElement.filePath)
|
||||||
}
|
}
|
||||||
})
|
}).then()
|
||||||
// 怎么拿到url呢
|
// 怎么拿到url呢
|
||||||
} else if (element.fileElement) {
|
} else if (element.fileElement) {
|
||||||
message_data["type"] = OB11MessageDataType.file;
|
message_data["type"] = OB11MessageDataType.file;
|
||||||
@ -158,7 +158,7 @@ export class OB11Constructor {
|
|||||||
// message_data["data"]["path"] = element.fileElement.filePath
|
// message_data["data"]["path"] = element.fileElement.filePath
|
||||||
// message_data["data"]["file_id"] = element.fileElement.fileUuid
|
// message_data["data"]["file_id"] = element.fileElement.fileUuid
|
||||||
message_data["data"]["file_size"] = element.fileElement.fileSize
|
message_data["data"]["file_size"] = element.fileElement.fileSize
|
||||||
fileCache.set(element.fileElement.fileName, {
|
dbUtil.addFileCache(element.fileElement.fileName, {
|
||||||
fileName: element.fileElement.fileName,
|
fileName: element.fileElement.fileName,
|
||||||
filePath: element.fileElement.filePath,
|
filePath: element.fileElement.filePath,
|
||||||
fileSize: element.fileElement.fileSize,
|
fileSize: element.fileElement.fileSize,
|
||||||
@ -166,7 +166,7 @@ export class OB11Constructor {
|
|||||||
await NTQQApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
await NTQQApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
||||||
element.elementId, null, element.fileElement.filePath)
|
element.elementId, null, element.fileElement.filePath)
|
||||||
}
|
}
|
||||||
})
|
}).then()
|
||||||
// 怎么拿到url呢
|
// 怎么拿到url呢
|
||||||
} else if (element.pttElement) {
|
} else if (element.pttElement) {
|
||||||
message_data["type"] = OB11MessageDataType.voice;
|
message_data["type"] = OB11MessageDataType.voice;
|
||||||
@ -174,11 +174,11 @@ export class OB11Constructor {
|
|||||||
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_size"] = element.pttElement.fileSize
|
message_data["data"]["file_size"] = element.pttElement.fileSize
|
||||||
fileCache.set(element.pttElement.fileName, {
|
dbUtil.addFileCache(element.pttElement.fileName, {
|
||||||
fileName: element.pttElement.fileName,
|
fileName: element.pttElement.fileName,
|
||||||
filePath: element.pttElement.filePath,
|
filePath: element.pttElement.filePath,
|
||||||
fileSize: element.pttElement.fileSize,
|
fileSize: element.pttElement.fileSize,
|
||||||
})
|
}).then()
|
||||||
|
|
||||||
// log("收到语音消息", msg)
|
// log("收到语音消息", msg)
|
||||||
// window.LLAPI.Ptt2Text(message.raw.msgId, message.peer, messages).then(text => {
|
// window.LLAPI.Ptt2Text(message.raw.msgId, message.peer, messages).then(text => {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import {DATA_DIR, isGIF, log} from "../common/utils";
|
import {DATA_DIR, isGIF, log} from "../common/utils";
|
||||||
import {v4 as uuidv4} from "uuid";
|
import {v4 as uuidv4} from "uuid";
|
||||||
import * as path from 'node:path';
|
import * as path from 'node:path';
|
||||||
import {fileCache} from "../common/data";
|
|
||||||
import * as fileType from 'file-type';
|
import * as fileType from 'file-type';
|
||||||
|
import {dbUtil} from "../common/db";
|
||||||
|
|
||||||
const fs = require("fs").promises;
|
const fs = require("fs").promises;
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ export async function uri2local(uri: string, fileName: string = null) {
|
|||||||
filePath = pathname
|
filePath = pathname
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const cache = fileCache.get(uri)
|
const cache = await dbUtil.getFileCache(uri);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
filePath = cache.filePath
|
filePath = cache.filePath
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user