From 80487e31f58eb26dfdcfc60c5b282987aa864788 Mon Sep 17 00:00:00 2001 From: idranme Date: Sat, 7 Sep 2024 03:03:33 +0800 Subject: [PATCH] chore --- src/common/utils/messageUnique.ts | 260 +++++++++++++++--------------- src/common/utils/table.ts | 112 ++++++------- 2 files changed, 186 insertions(+), 186 deletions(-) diff --git a/src/common/utils/messageUnique.ts b/src/common/utils/messageUnique.ts index 3df7330..2d9ea0b 100644 --- a/src/common/utils/messageUnique.ts +++ b/src/common/utils/messageUnique.ts @@ -10,154 +10,154 @@ import { DATA_DIR } from '../globalVars' import { FileCacheV2 } from '../types' interface SQLiteTables extends Tables { - message: { - shortId: number - msgId: string - chatType: number - peerUid: string - } - file_v2: FileCacheV2 + message: { + shortId: number + msgId: string + chatType: number + peerUid: string + } + file_v2: FileCacheV2 } interface MsgIdAndPeerByShortId { - MsgId: string - Peer: Peer + MsgId: string + Peer: Peer } // forked from https://github.com/NapNeko/NapCatQQ/blob/6f6b258f22d7563f15d84e7172c4d4cbb547f47e/src/common/utils/MessageUnique.ts#L84 class MessageUniqueWrapper { - private msgDataMap: LimitedHashTable - private msgIdMap: LimitedHashTable - private db: Database | undefined + private msgDataMap: LimitedHashTable + private msgIdMap: LimitedHashTable + private db: Database | undefined - constructor(maxMap: number = 1000) { - this.msgIdMap = new LimitedHashTable(maxMap) - this.msgDataMap = new LimitedHashTable(maxMap) + constructor(maxMap: number = 1000) { + this.msgIdMap = new LimitedHashTable(maxMap) + this.msgDataMap = new LimitedHashTable(maxMap) + } + + async init(uin: string) { + const dbDir = path.join(DATA_DIR, 'database') + if (!fs.existsSync(dbDir)) { + await fsPromise.mkdir(dbDir) } + const database = new Database() + await database.connect(SQLite, { + path: path.join(dbDir, `${uin}.db`) + }) + database.extend('message', { + shortId: 'integer(10)', + chatType: 'unsigned', + msgId: 'string(24)', + peerUid: 'string(24)' + }, { + primary: 'shortId' + }) + database.extend('file_v2', { + fileName: 'string', + fileSize: 'string', + fileUuid: 'string(128)', + msgId: 'string(24)', + msgTime: 'unsigned(10)', + peerUid: 'string(24)', + chatType: 'unsigned', + elementId: 'string(24)', + elementType: 'unsigned', + }, { + primary: 'fileUuid', + indexes: ['fileName'] + }) + this.db = database + } - async init(uin: string) { - const dbDir = path.join(DATA_DIR, 'database') - if (!fs.existsSync(dbDir)) { - await fsPromise.mkdir(dbDir) + async getRecentMsgIds(Peer: Peer, size: number): Promise { + const heads = this.msgIdMap.getHeads(size) + if (!heads) { + return [] + } + const data: (MsgIdAndPeerByShortId | undefined)[] = [] + for (const t of heads) { + data.push(await MessageUnique.getMsgIdAndPeerByShortId(t.value)) + } + const ret = data.filter((t) => t?.Peer.chatType === Peer.chatType && t?.Peer.peerUid === Peer.peerUid) + return ret.map((t) => t?.MsgId).filter((t) => t !== undefined) + } + + createMsg(peer: Peer, msgId: string): number { + const key = `${msgId}|${peer.chatType}|${peer.peerUid}` + const hash = createHash('md5').update(key).digest() + //设置第一个bit为0 保证shortId为正数 + hash[0] &= 0x7f + const shortId = hash.readInt32BE(0) + //减少性能损耗 + // const isExist = this.msgIdMap.getKey(shortId) + // if (isExist && isExist === msgId) { + // return shortId + // } + this.msgIdMap.set(msgId, shortId) + this.msgDataMap.set(key, shortId) + this.db?.upsert('message', [{ + msgId, + shortId, + chatType: peer.chatType, + peerUid: peer.peerUid + }], 'shortId').then() + return shortId + } + + async getMsgIdAndPeerByShortId(shortId: number): Promise { + const data = this.msgDataMap.getKey(shortId) + if (data) { + const [msgId, chatTypeStr, peerUid] = data.split('|') + const peer: Peer = { + chatType: parseInt(chatTypeStr), + peerUid, + guildId: '', + } + return { MsgId: msgId, Peer: peer } + } + const items = await this.db?.get('message', { shortId }) + if (items?.length) { + const { msgId, chatType, peerUid } = items[0] + return { + MsgId: msgId, + Peer: { + chatType, + peerUid, + guildId: '', } - const database = new Database() - await database.connect(SQLite, { - path: path.join(dbDir, `${uin}.db`) - }) - database.extend('message', { - shortId: 'integer(10)', - chatType: 'unsigned', - msgId: 'string(24)', - peerUid: 'string(24)' - }, { - primary: 'shortId' - }) - database.extend('file_v2', { - fileName: 'string', - fileSize: 'string', - fileUuid: 'string(128)', - msgId: 'string(24)', - msgTime: 'unsigned(10)', - peerUid: 'string(24)', - chatType: 'unsigned', - elementId: 'string(24)', - elementType: 'unsigned', - }, { - primary: 'fileUuid', - indexes: ['fileName'] - }) - this.db = database + } } + return undefined + } - async getRecentMsgIds(Peer: Peer, size: number): Promise { - const heads = this.msgIdMap.getHeads(size) - if (!heads) { - return [] - } - const data: (MsgIdAndPeerByShortId | undefined)[] = [] - for (const t of heads) { - data.push(await MessageUnique.getMsgIdAndPeerByShortId(t.value)) - } - const ret = data.filter((t) => t?.Peer.chatType === Peer.chatType && t?.Peer.peerUid === Peer.peerUid) - return ret.map((t) => t?.MsgId).filter((t) => t !== undefined) - } + getShortIdByMsgId(msgId: string): number | undefined { + return this.msgIdMap.getValue(msgId) + } - createMsg(peer: Peer, msgId: string): number { - const key = `${msgId}|${peer.chatType}|${peer.peerUid}` - const hash = createHash('md5').update(key).digest() - //设置第一个bit为0 保证shortId为正数 - hash[0] &= 0x7f - const shortId = hash.readInt32BE(0) - //减少性能损耗 - // const isExist = this.msgIdMap.getKey(shortId) - // if (isExist && isExist === msgId) { - // return shortId - // } - this.msgIdMap.set(msgId, shortId) - this.msgDataMap.set(key, shortId) - this.db?.upsert('message', [{ - msgId, - shortId, - chatType: peer.chatType, - peerUid: peer.peerUid - }], 'shortId').then() - return shortId - } + async getPeerByMsgId(msgId: string) { + const shortId = this.msgIdMap.getValue(msgId) + if (!shortId) return undefined + return await this.getMsgIdAndPeerByShortId(shortId) + } - async getMsgIdAndPeerByShortId(shortId: number): Promise { - const data = this.msgDataMap.getKey(shortId) - if (data) { - const [msgId, chatTypeStr, peerUid] = data.split('|') - const peer: Peer = { - chatType: parseInt(chatTypeStr), - peerUid, - guildId: '', - } - return { MsgId: msgId, Peer: peer } - } - const items = await this.db?.get('message', { shortId }) - if (items?.length) { - const { msgId, chatType, peerUid } = items[0] - return { - MsgId: msgId, - Peer: { - chatType, - peerUid, - guildId: '', - } - } - } - return undefined - } + resize(maxSize: number): void { + this.msgIdMap.resize(maxSize) + this.msgDataMap.resize(maxSize) + } - getShortIdByMsgId(msgId: string): number | undefined { - return this.msgIdMap.getValue(msgId) - } + addFileCache(data: FileCacheV2) { + return this.db?.upsert('file_v2', [data], 'fileUuid') + } - async getPeerByMsgId(msgId: string) { - const shortId = this.msgIdMap.getValue(msgId) - if (!shortId) return undefined - return await this.getMsgIdAndPeerByShortId(shortId) - } + getFileCacheByName(fileName: string) { + return this.db?.get('file_v2', { fileName }, { + sort: { msgTime: 'desc' } + }) + } - resize(maxSize: number): void { - this.msgIdMap.resize(maxSize) - this.msgDataMap.resize(maxSize) - } - - addFileCache(data: FileCacheV2) { - return this.db?.upsert('file_v2', [data], 'fileUuid') - } - - getFileCacheByName(fileName: string) { - return this.db?.get('file_v2', { fileName }, { - sort: { msgTime: 'desc' } - }) - } - - getFileCacheById(fileUuid: string) { - return this.db?.get('file_v2', { fileUuid }) - } + getFileCacheById(fileUuid: string) { + return this.db?.get('file_v2', { fileUuid }) + } } export const MessageUnique: MessageUniqueWrapper = new MessageUniqueWrapper() \ No newline at end of file diff --git a/src/common/utils/table.ts b/src/common/utils/table.ts index bd2a6e0..29738af 100644 --- a/src/common/utils/table.ts +++ b/src/common/utils/table.ts @@ -1,72 +1,72 @@ // forked from https://github.com/NapNeko/NapCatQQ/blob/6f6b258f22d7563f15d84e7172c4d4cbb547f47e/src/common/utils/MessageUnique.ts#L5 export class LimitedHashTable { - private keyToValue: Map = new Map() - private valueToKey: Map = new Map() - private maxSize: number + private keyToValue: Map = new Map() + private valueToKey: Map = new Map() + private maxSize: number - constructor(maxSize: number) { - this.maxSize = maxSize - } + constructor(maxSize: number) { + this.maxSize = maxSize + } - resize(count: number) { - this.maxSize = count - } + resize(count: number) { + this.maxSize = count + } - set(key: K, value: V): void { - this.keyToValue.set(key, value) - this.valueToKey.set(value, key) - while (this.keyToValue.size !== this.valueToKey.size) { - console.log('keyToValue.size !== valueToKey.size Error Atom') - this.keyToValue.clear() - this.valueToKey.clear() - } - while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) { - const oldestKey = this.keyToValue.keys().next().value - this.valueToKey.delete(this.keyToValue.get(oldestKey)!) - this.keyToValue.delete(oldestKey) - } + set(key: K, value: V): void { + this.keyToValue.set(key, value) + this.valueToKey.set(value, key) + while (this.keyToValue.size !== this.valueToKey.size) { + console.log('keyToValue.size !== valueToKey.size Error Atom') + this.keyToValue.clear() + this.valueToKey.clear() } + while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) { + const oldestKey = this.keyToValue.keys().next().value + this.valueToKey.delete(this.keyToValue.get(oldestKey)!) + this.keyToValue.delete(oldestKey) + } + } - getValue(key: K): V | undefined { - return this.keyToValue.get(key) - } + getValue(key: K): V | undefined { + return this.keyToValue.get(key) + } - getKey(value: V): K | undefined { - return this.valueToKey.get(value) - } + getKey(value: V): K | undefined { + return this.valueToKey.get(value) + } - deleteByValue(value: V): void { - const key = this.valueToKey.get(value) - if (key !== undefined) { - this.keyToValue.delete(key) - this.valueToKey.delete(value) - } + deleteByValue(value: V): void { + const key = this.valueToKey.get(value) + if (key !== undefined) { + this.keyToValue.delete(key) + this.valueToKey.delete(value) } + } - deleteByKey(key: K): void { - const value = this.keyToValue.get(key) - if (value !== undefined) { - this.keyToValue.delete(key) - this.valueToKey.delete(value) - } + deleteByKey(key: K): void { + const value = this.keyToValue.get(key) + if (value !== undefined) { + this.keyToValue.delete(key) + this.valueToKey.delete(value) } + } - getKeyList(): K[] { - return Array.from(this.keyToValue.keys()) - } + getKeyList(): K[] { + return Array.from(this.keyToValue.keys()) + } - //获取最近刚写入的几个值 - getHeads(size: number): { key: K; value: V }[] | undefined { - const keyList = this.getKeyList() - if (keyList.length === 0) { - return undefined - } - const result: { key: K; value: V }[] = [] - const listSize = Math.min(size, keyList.length) - for (let i = 0; i < listSize; i++) { - const key = keyList[listSize - i] - result.push({ key, value: this.keyToValue.get(key)! }) - } - return result + //获取最近刚写入的几个值 + getHeads(size: number): { key: K; value: V }[] | undefined { + const keyList = this.getKeyList() + if (keyList.length === 0) { + return undefined } + const result: { key: K; value: V }[] = [] + const listSize = Math.min(size, keyList.length) + for (let i = 0; i < listSize; i++) { + const key = keyList[listSize - i] + result.push({ key, value: this.keyToValue.get(key)! }) + } + return result + } } \ No newline at end of file