diff --git a/package.json b/package.json index 10d7156..6795284 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "author": "", "license": "MIT", "dependencies": { - "@minatojs/driver-sqlite": "4.5.0", + "@minatojs/driver-sqlite": "^4.6.0", "compressing": "^1.10.1", "cordis": "^3.18.1", "cors": "^2.8.5", @@ -26,7 +26,7 @@ "fast-xml-parser": "^4.5.0", "file-type": "^19.5.0", "fluent-ffmpeg": "^2.1.3", - "minato": "3.5.1", + "minato": "^3.6.0", "protobufjs": "^7.4.0", "silk-wasm": "^3.6.1", "ws": "^8.18.0" diff --git a/src/common/utils/messageUnique.ts b/src/common/utils/messageUnique.ts deleted file mode 100644 index 6a615d4..0000000 --- a/src/common/utils/messageUnique.ts +++ /dev/null @@ -1,162 +0,0 @@ -import fsPromise from 'node:fs/promises' -import fs from 'node:fs' -import path from 'node:path' -import Database, { Tables } from 'minato' -import SQLite from '@minatojs/driver-sqlite' -import { Peer } from '@/ntqqapi/types' -import { createHash } from 'node:crypto' -import { LimitedHashTable } from './table' -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 -} - -interface MsgIdAndPeerByShortId { - 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 - - 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 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: '', - } - } - } - } - - getShortIdByMsgId(msgId: string): number | undefined { - return this.msgIdMap.getValue(msgId) - } - - async getPeerByMsgId(msgId: string) { - const shortId = this.msgIdMap.getValue(msgId) - if (!shortId) return undefined - return await this.getMsgIdAndPeerByShortId(shortId) - } - - 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 }) - } -} - -export const MessageUnique: MessageUniqueWrapper = new MessageUniqueWrapper() diff --git a/src/main/main.ts b/src/main/main.ts index de4aa71..5ce2a50 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,5 +1,4 @@ import path from 'node:path' -import fs from 'node:fs' import Log from './log' import Core from '../ntqqapi/core' import OneBot11Adapter from '../onebot11/adapter' @@ -34,6 +33,11 @@ import { NTQQWebApi, NTQQWindowApi } from '../ntqqapi/api' +import { mkdir } from 'node:fs/promises' +import { existsSync, mkdirSync } from 'node:fs' +import Database from 'minato' +import SQLiteDriver from '@minatojs/driver-sqlite' +import Store from './store' declare module 'cordis' { interface Events { @@ -45,12 +49,12 @@ let mainWindow: BrowserWindow | null = null // 加载插件时触发 function onLoad() { - if (!fs.existsSync(DATA_DIR)) { - fs.mkdirSync(DATA_DIR, { recursive: true }) + if (!existsSync(DATA_DIR)) { + mkdirSync(DATA_DIR, { recursive: true }) } - if (!fs.existsSync(LOG_DIR)) { - fs.mkdirSync(LOG_DIR) + if (!existsSync(LOG_DIR)) { + mkdirSync(LOG_DIR) } ipcMain.handle(CHANNEL_CHECK_VERSION, async () => { @@ -151,8 +155,12 @@ function onLoad() { log('LLOneBot 开关设置为关闭,不启动LLOneBot') return } - if (!fs.existsSync(TEMP_DIR)) { - fs.mkdirSync(TEMP_DIR) + if (!existsSync(TEMP_DIR)) { + await mkdir(TEMP_DIR) + } + const dbDir = path.join(DATA_DIR, 'database') + if (!existsSync(dbDir)) { + await mkdir(dbDir) } const ctx = new Context() ctx.plugin(Log, { @@ -179,6 +187,11 @@ function onLoad() { enableLocalFile2Url: config.enableLocalFile2Url!, ffmpeg: config.ffmpeg, }) + ctx.plugin(Database) + ctx.plugin(SQLiteDriver, { + path: path.join(dbDir, `${selfInfo.uin}.db`) + }) + ctx.plugin(Store) ctx.start() ipcMain.on(CHANNEL_SET_CONFIG_CONFIRMED, (event, config: LLOBConfig) => { ctx.parallel('llonebot/config-updated', config) diff --git a/src/main/store.ts b/src/main/store.ts new file mode 100644 index 0000000..a0c31b7 --- /dev/null +++ b/src/main/store.ts @@ -0,0 +1,126 @@ +import { Peer } from '@/ntqqapi/types' +import { createHash } from 'node:crypto' +import { LimitedHashTable } from '@/common/utils/table' +import { FileCacheV2 } from '@/common/types' +import { Context, Service } from 'cordis' + +declare module 'cordis' { + interface Context { + store: Store + } + interface Tables { + message: { + shortId: number + msgId: string + chatType: number + peerUid: string + } + file_v2: FileCacheV2 + } +} + +interface MsgInfo { + msgId: string + peer: Peer +} + +export default class Store extends Service { + static inject = ['database', 'model'] + private cache: LimitedHashTable + + constructor(protected ctx: Context) { + super(ctx, 'store', true) + this.cache = new LimitedHashTable(1000) + this.initDatabase() + } + + private async initDatabase() { + this.ctx.model.extend('message', { + shortId: 'integer(10)', + chatType: 'unsigned', + msgId: 'string(24)', + peerUid: 'string(24)' + }, { + primary: 'shortId' + }) + this.ctx.model.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'] + }) + } + + createMsgShortId(peer: Peer, msgId: string): number { + const cacheKey = `${msgId}|${peer.chatType}|${peer.peerUid}` + const hash = createHash('md5').update(cacheKey).digest() + hash[0] &= 0x7f //设置第一个bit为0 保证shortId为正数 + const shortId = hash.readInt32BE() + this.cache.set(cacheKey, shortId) + this.ctx.database.upsert('message', [{ + msgId, + shortId, + chatType: peer.chatType, + peerUid: peer.peerUid + }], 'shortId').then() + return shortId + } + + async getMsgInfoByShortId(shortId: number): Promise { + const data = this.cache.getKey(shortId) + if (data) { + const [msgId, chatTypeStr, peerUid] = data.split('|') + return { + msgId, + peer: { + chatType: +chatTypeStr, + peerUid, + guildId: '' + } + } + } + const items = await this.ctx.database.get('message', { shortId }) + if (items?.length) { + const { msgId, chatType, peerUid } = items[0] + return { + msgId, + peer: { + chatType, + peerUid, + guildId: '' + } + } + } + } + + async getShortIdByMsgId(msgId: string): Promise { + return (await this.ctx.database.get('message', { msgId }))[0]?.shortId + } + + getShortIdByMsgInfo(peer: Peer, msgId: string) { + const cacheKey = `${msgId}|${peer.chatType}|${peer.peerUid}` + return this.cache.getValue(cacheKey) + } + + addFileCache(data: FileCacheV2) { + return this.ctx.database.upsert('file_v2', [data], 'fileUuid') + } + + getFileCacheByName(fileName: string) { + return this.ctx.database.get('file_v2', { fileName }, { + sort: { msgTime: 'desc' } + }) + } + + getFileCacheById(fileUuid: string) { + return this.ctx.database.get('file_v2', { fileUuid }) + } +} diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index 0458169..3ab7703 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -233,34 +233,48 @@ export class NTQQGroupApi extends Service { >(NTMethod.GROUP_AT_ALL_REMAIN_COUNT, [{ groupCode }, null]) } - /** 27187 TODO */ async removeGroupEssence(groupCode: string, msgId: string) { const session = getSession() - // 代码没测过 - // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom - const data = await session?.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false) - const param = { - groupCode: groupCode, - msgRandom: Number(data?.msgList[0].msgRandom), - msgSeq: Number(data?.msgList[0].msgSeq) + if (session) { + const data = await session.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false) + return session.getGroupService().removeGroupEssence({ + groupCode: groupCode, + msgRandom: Number(data?.msgList[0].msgRandom), + msgSeq: Number(data?.msgList[0].msgSeq) + }) + } else { + const ntMsgApi = this.ctx.get('ntMsgApi')! + const data = await ntMsgApi.getMsgHistory({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false) + return await invoke('nodeIKernelGroupService/removeGroupEssence', [{ + req: { + groupCode: groupCode, + msgRandom: Number(data?.msgList[0].msgRandom), + msgSeq: Number(data?.msgList[0].msgSeq) + } + }, null]) } - // GetMsgByShoretID(ShoretID) -> MsgService.getMsgs(Peer,MsgId,1,false) -> 组出参数 - return session?.getGroupService().removeGroupEssence(param) } - /** 27187 TODO */ async addGroupEssence(groupCode: string, msgId: string) { const session = getSession() - // 代码没测过 - // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom - const data = await session?.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false) - const param = { - groupCode: groupCode, - msgRandom: Number(data?.msgList[0].msgRandom), - msgSeq: Number(data?.msgList[0].msgSeq) + if (session) { + const data = await session.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false) + return session.getGroupService().addGroupEssence({ + groupCode: groupCode, + msgRandom: Number(data?.msgList[0].msgRandom), + msgSeq: Number(data?.msgList[0].msgSeq) + }) + } else { + const ntMsgApi = this.ctx.get('ntMsgApi')! + const data = await ntMsgApi.getMsgHistory({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false) + return await invoke('nodeIKernelGroupService/addGroupEssence', [{ + req: { + groupCode: groupCode, + msgRandom: Number(data?.msgList[0].msgRandom), + msgSeq: Number(data?.msgList[0].msgSeq) + } + }, null]) } - // GetMsgByShoretID(ShoretID) -> MsgService.getMsgs(Peer,MsgId,1,false) -> 组出参数 - return session?.getGroupService().addGroupEssence(param) } async createGroupFileFolder(groupId: string, folderName: string) { @@ -311,4 +325,14 @@ export class NTQQGroupApi extends Service { const ret = await invoke('nodeIKernelGroupService/getGroupRecommendContactArkJson', [{ groupCode }, null]) return ret.arkJson } + + async queryCachedEssenceMsg(groupCode: string, msgSeq = '0', msgRandom = '0') { + return await invoke('nodeIKernelGroupService/queryCachedEssenceMsg', [{ + key: { + groupCode, + msgSeq: +msgSeq, + msgRandom: +msgRandom + } + }, null]) + } } diff --git a/src/ntqqapi/api/user.ts b/src/ntqqapi/api/user.ts index 9884fdb..690b385 100644 --- a/src/ntqqapi/api/user.ts +++ b/src/ntqqapi/api/user.ts @@ -102,18 +102,6 @@ export class NTQQUserApi extends Service { return await invoke('nodeIKernelTipOffService/getPskey', [{ domains, isForNewPCQQ: true }, null]) } - genBkn(sKey: string) { - sKey = sKey || '' - let hash = 5381 - - for (let i = 0; i < sKey.length; i++) { - const code = sKey.charCodeAt(i) - hash = hash + (hash << 5) + code - } - - return (hash & 0x7fffffff).toString() - } - async like(uid: string, count = 1) { const session = getSession() if (session) { diff --git a/src/ntqqapi/api/webapi.ts b/src/ntqqapi/api/webapi.ts index fdaaff2..17799c4 100644 --- a/src/ntqqapi/api/webapi.ts +++ b/src/ntqqapi/api/webapi.ts @@ -75,30 +75,6 @@ export interface GroupEssenceMsgRet { } } -interface SetGroupNoticeParams { - groupCode: string - content: string - pinned: number - type: number - isShowEditCard: number - tipWindowType: number - confirmRequired: number - picId: string - imgWidth?: number - imgHeight?: number -} - -interface SetGroupNoticeRet { - ec: number - em: string - id: number - ltsm: number - new_fid: string - read_only: number - role: number - srv_code: number -} - export class NTQQWebApi extends Service { static inject = ['ntUserApi'] @@ -274,65 +250,7 @@ export class NTQQWebApi extends Service { return honorInfo } - async setGroupNotice(params: SetGroupNoticeParams): Promise { - const cookieObject = await this.ctx.ntUserApi.getCookies('qun.qq.com') - const settings = JSON.stringify({ - is_show_edit_card: params.isShowEditCard, - tip_window_type: params.tipWindowType, - confirm_required: params.confirmRequired - }) - - return await RequestUtil.HttpGetJson( - `https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?${new URLSearchParams({ - bkn: this.genBkn(cookieObject.skey), - qid: params.groupCode, - text: params.content, - pinned: params.pinned.toString(), - type: params.type.toString(), - settings: settings, - ...(params.picId !== '' && { - pic: params.picId, - imgWidth: params.imgWidth?.toString(), - imgHeight: params.imgHeight?.toString(), - }) - })}`, - 'POST', - '', - { 'Cookie': this.cookieToString(cookieObject) } - ) - } - private cookieToString(cookieObject: Dict) { return Object.entries(cookieObject).map(([key, value]) => `${key}=${value}`).join('; ') } - - async findGroupEssenceMsg(groupCode: string, msgSeq: number) { - for (let i = 0; i < 20; i++) { - const res = await this.getGroupEssenceMsgList(groupCode, i, 50) - if (!res) break - const msg = res.data.msg_list.find(e => e.msg_seq === msgSeq) - if (msg) return msg - if (res.data.is_end) break - } - } - - async getGroupEssenceMsgList(groupCode: string, pageStart: number, pageLimit: number) { - const cookieObject = await this.ctx.ntUserApi.getCookies('qun.qq.com') - try { - const ret = await RequestUtil.HttpGetJson( - `https://qun.qq.com/cgi-bin/group_digest/digest_list?${new URLSearchParams({ - bkn: this.genBkn(cookieObject.skey), - page_start: pageStart.toString(), - page_limit: pageLimit.toString(), - group_code: groupCode, - })}`, - 'GET', - '', - { 'Cookie': this.cookieToString(cookieObject) } - ) - return ret.retcode === 0 ? ret : undefined - } catch { - return undefined - } - } } diff --git a/src/ntqqapi/core.ts b/src/ntqqapi/core.ts index 8b247fc..f1fd090 100644 --- a/src/ntqqapi/core.ts +++ b/src/ntqqapi/core.ts @@ -1,7 +1,6 @@ import fs from 'node:fs' import { Service, Context } from 'cordis' import { registerCallHook, registerReceiveHook, ReceiveCmdS } from './hook' -import { MessageUnique } from '../common/utils/messageUnique' import { Config as LLOBConfig } from '../common/types' import { llonebotError } from '../common/globalVars' import { isNumeric } from '../common/utils/misc' @@ -45,7 +44,6 @@ class Core extends Service { public start() { llonebotError.otherError = '' - MessageUnique.init(selfInfo.uin) this.registerListener() this.ctx.logger.info(`LLOneBot/${version}`) this.ctx.on('llonebot/config-updated', input => { diff --git a/src/ntqqapi/services/NodeIKernelGroupService.ts b/src/ntqqapi/services/NodeIKernelGroupService.ts index 1bbeb91..9e74f35 100644 --- a/src/ntqqapi/services/NodeIKernelGroupService.ts +++ b/src/ntqqapi/services/NodeIKernelGroupService.ts @@ -72,14 +72,24 @@ export interface NodeIKernelGroupService { } }): Promise - //26702(其实更早 但是我不知道) - isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise + isEssenceMsg(req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise - //26702(其实更早 但是我不知道) - queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise + queryCachedEssenceMsg(req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<{ + items: { + groupCode: string + msgSeq: number + msgRandom: number + msgSenderUin: string + msgSenderNick: string + opType: number + opUin: string + opNick: string + opTime: number + grayTipSeq: string + }[] + }> - //26702(其实更早 但是我不知道) - fetchGroupEssenceList(Req: { groupCode: string, pageStart: number, pageLimit: number }, Arg: unknown): Promise + fetchGroupEssenceList(req: { groupCode: string, pageStart: number, pageLimit: number }, arg: unknown): Promise //26702 getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{ diff --git a/src/onebot11/action/file/GetFile.ts b/src/onebot11/action/file/GetFile.ts index d8bdb56..18e8a10 100644 --- a/src/onebot11/action/file/GetFile.ts +++ b/src/onebot11/action/file/GetFile.ts @@ -2,7 +2,6 @@ import { BaseAction, Schema } from '../BaseAction' import { readFile } from 'node:fs/promises' import { ActionName } from '../types' import { Peer, ElementType } from '@/ntqqapi/types' -import { MessageUnique } from '@/common/utils/messageUnique' export interface GetFilePayload { file: string // 文件名或者fileUuid @@ -24,9 +23,9 @@ export abstract class GetFileBase extends BaseAction { const { enableLocalFile2Url } = this.adapter.config - let fileCache = await MessageUnique.getFileCacheById(payload.file) + let fileCache = await this.ctx.store.getFileCacheById(payload.file) if (!fileCache?.length) { - fileCache = await MessageUnique.getFileCacheByName(payload.file) + fileCache = await this.ctx.store.getFileCacheByName(payload.file) } if (fileCache?.length) { diff --git a/src/onebot11/action/go-cqhttp/DelEssenceMsg.ts b/src/onebot11/action/go-cqhttp/DelEssenceMsg.ts index f96c09a..a4815bd 100644 --- a/src/onebot11/action/go-cqhttp/DelEssenceMsg.ts +++ b/src/onebot11/action/go-cqhttp/DelEssenceMsg.ts @@ -1,6 +1,5 @@ import { BaseAction, Schema } from '../BaseAction' import { ActionName } from '../types' -import { MessageUnique } from '@/common/utils/messageUnique' interface Payload { message_id: number | string @@ -13,13 +12,13 @@ export class DelEssenceMsg extends BaseAction { }) protected async _handle(payload: Payload) { - const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id) + const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id) if (!msg) { throw new Error('msg not found') } return await this.ctx.ntGroupApi.removeGroupEssence( - msg.Peer.peerUid, - msg.MsgId, + msg.peer.peerUid, + msg.msgId, ) } } diff --git a/src/onebot11/action/go-cqhttp/GetForwardMsg.ts b/src/onebot11/action/go-cqhttp/GetForwardMsg.ts index 53f3c47..455b0f5 100644 --- a/src/onebot11/action/go-cqhttp/GetForwardMsg.ts +++ b/src/onebot11/action/go-cqhttp/GetForwardMsg.ts @@ -2,7 +2,6 @@ import { BaseAction, Schema } from '../BaseAction' import { OB11ForwardMessage } from '../../types' import { OB11Entities } from '../../entities' import { ActionName } from '../types' -import { MessageUnique } from '@/common/utils/messageUnique' import { filterNullable } from '@/common/utils/misc' interface Payload { @@ -26,12 +25,12 @@ export class GetForwardMsg extends BaseAction { if (!msgId) { throw Error('message_id不能为空') } - const rootMsgId = MessageUnique.getShortIdByMsgId(msgId) - const rootMsg = await MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || +msgId) + const rootMsgId = await this.ctx.store.getShortIdByMsgId(msgId) + const rootMsg = await this.ctx.store.getMsgInfoByShortId(rootMsgId || +msgId) if (!rootMsg) { throw Error('msg not found') } - const data = await this.ctx.ntMsgApi.getMultiMsg(rootMsg.Peer, rootMsg.MsgId, rootMsg.MsgId) + const data = await this.ctx.ntMsgApi.getMultiMsg(rootMsg.peer, rootMsg.msgId, rootMsg.msgId) if (data?.result !== 0) { throw Error('找不到相关的聊天记录' + data?.errMsg) } @@ -40,7 +39,7 @@ export class GetForwardMsg extends BaseAction { msgList.map(async (msg) => { const resMsg = await OB11Entities.message(this.ctx, msg) if (!resMsg) return - resMsg.message_id = MessageUnique.createMsg({ + resMsg.message_id = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid, }, msg.msgId) diff --git a/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts b/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts index 1dd0b0c..cbcf6f8 100644 --- a/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts +++ b/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts @@ -4,7 +4,6 @@ import { ActionName } from '../types' import { ChatType } from '@/ntqqapi/types' import { OB11Entities } from '../../entities' import { RawMessage } from '@/ntqqapi/types' -import { MessageUnique } from '@/common/utils/messageUnique' import { filterNullable } from '@/common/utils/misc' interface Payload { @@ -35,7 +34,7 @@ export class GetGroupMsgHistory extends BaseAction { if (!payload.message_seq) { msgList = (await this.ctx.ntMsgApi.getAioFirstViewLatestMsgs(peer, +count)).msgList } else { - const startMsgId = (await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq))?.MsgId + const startMsgId = (await this.ctx.store.getMsgInfoByShortId(+payload.message_seq))?.msgId if (!startMsgId) throw new Error(`消息${payload.message_seq}不存在`) msgList = (await this.ctx.ntMsgApi.getMsgHistory(peer, startMsgId, +count)).msgList } @@ -43,7 +42,7 @@ export class GetGroupMsgHistory extends BaseAction { if (reverseOrder) msgList.reverse() await Promise.all( msgList.map(async msg => { - msg.msgShortId = MessageUnique.createMsg({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId) + msg.msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId) }) ) const ob11MsgList = await Promise.all(msgList.map((msg) => OB11Entities.message(this.ctx, msg))) diff --git a/src/onebot11/action/go-cqhttp/MarkMsgAsRead.ts b/src/onebot11/action/go-cqhttp/MarkMsgAsRead.ts index 8c73cae..2ef64b1 100644 --- a/src/onebot11/action/go-cqhttp/MarkMsgAsRead.ts +++ b/src/onebot11/action/go-cqhttp/MarkMsgAsRead.ts @@ -1,6 +1,5 @@ import { BaseAction, Schema } from '../BaseAction' import { ActionName } from '../types' -import { MessageUnique } from '@/common/utils/messageUnique' interface Payload { message_id: number | string @@ -13,11 +12,11 @@ export class MarkMsgAsRead extends BaseAction { }) protected async _handle(payload: Payload) { - const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id) + const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id) if (!msg) { throw new Error('msg not found') } - await this.ctx.ntMsgApi.setMsgRead(msg.Peer) + await this.ctx.ntMsgApi.setMsgRead(msg.peer) return null } } diff --git a/src/onebot11/action/go-cqhttp/SendForwardMsg.ts b/src/onebot11/action/go-cqhttp/SendForwardMsg.ts index c76cd63..f751eaa 100644 --- a/src/onebot11/action/go-cqhttp/SendForwardMsg.ts +++ b/src/onebot11/action/go-cqhttp/SendForwardMsg.ts @@ -4,7 +4,6 @@ import { ActionName } from '../types' import { BaseAction, Schema } from '../BaseAction' import { Peer } from '@/ntqqapi/types/msg' import { ChatType, ElementType, RawMessage, SendMessageElement } from '@/ntqqapi/types' -import { MessageUnique } from '@/common/utils/messageUnique' import { selfInfo } from '@/common/globalVars' import { convertMessage2List, createSendElements, sendMsg, createPeer, CreatePeerMode } from '../../helper/createMessage' @@ -57,7 +56,7 @@ export class SendForwardMsg extends BaseAction { peerUid: selfInfo.uid } const nodeMsg = await this.ctx.ntMsgApi.sendMsg(peer, sendElements) - await this.ctx.sleep(400) + await this.ctx.sleep(300) return nodeMsg } catch (e) { this.ctx.logger.warn(e, '克隆转发消息失败,将忽略本条消息', msg) @@ -70,19 +69,19 @@ export class SendForwardMsg extends BaseAction { chatType: ChatType.friend, peerUid: selfInfo.uid, } - let nodeMsgIds: string[] = [] + const nodeMsgIds: { msgId: string, peer: Peer }[] = [] // 先判断一遍是不是id和自定义混用 for (const messageNode of messageNodes) { // 一个node表示一个人的消息 const nodeId = messageNode.data.id // 有nodeId表示一个子转发消息卡片 if (nodeId) { - const nodeMsg = await MessageUnique.getMsgIdAndPeerByShortId(+nodeId) || await MessageUnique.getPeerByMsgId(nodeId) + const nodeMsg = await this.ctx.store.getMsgInfoByShortId(+nodeId) if (!nodeMsg) { this.ctx.logger.warn('转发消息失败,未找到消息', nodeId) continue } - nodeMsgIds.push(nodeMsg.MsgId) + nodeMsgIds.push(nodeMsg) } else { // 自定义的消息 @@ -111,17 +110,16 @@ export class SendForwardMsg extends BaseAction { else { sendElementsSplit[splitIndex].push(ele) } - this.ctx.logger.info(sendElementsSplit) } - // log("分割后的转发节点", sendElementsSplit) + this.ctx.logger.info('分割后的转发节点', sendElementsSplit) for (const eles of sendElementsSplit) { const nodeMsg = await sendMsg(this.ctx, selfPeer, eles, []) if (!nodeMsg) { this.ctx.logger.warn('转发节点生成失败', eles) continue } - nodeMsgIds.push(nodeMsg.msgId) - await this.ctx.sleep(400) + nodeMsgIds.push({ msgId: nodeMsg.msgId, peer: selfPeer }) + await this.ctx.sleep(300) } deleteAfterSentFiles.map(path => unlink(path)) } catch (e) { @@ -132,31 +130,34 @@ export class SendForwardMsg extends BaseAction { // 检查srcPeer是否一致,不一致则需要克隆成自己的消息, 让所有srcPeer都变成自己的,使其保持一致才能够转发 const nodeMsgArray: RawMessage[] = [] - let srcPeer: Peer | null = null + let srcPeer: Peer let needSendSelf = false - for (const msgId of nodeMsgIds) { - const nodeMsgPeer = await MessageUnique.getPeerByMsgId(msgId) - if (nodeMsgPeer) { - const nodeMsg = (await this.ctx.ntMsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0] - srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid } - if (srcPeer.peerUid !== nodeMsg.peerUid) { - needSendSelf = true - } - nodeMsgArray.push(nodeMsg) + for (const { msgId, peer } of nodeMsgIds) { + const nodeMsg = (await this.ctx.ntMsgApi.getMsgsByMsgId(peer, [msgId])).msgList[0] + srcPeer ??= { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid } + if (srcPeer.peerUid !== nodeMsg.peerUid) { + needSendSelf = true } + nodeMsgArray.push(nodeMsg) } - nodeMsgIds = nodeMsgArray.map((msg) => msg.msgId) + let retMsgIds: string[] = [] if (needSendSelf) { for (const msg of nodeMsgArray) { - if (msg.peerUid === selfPeer.peerUid) continue - await this.cloneMsg(msg) + if (msg.peerUid === selfPeer.peerUid) { + retMsgIds.push(msg.msgId) + continue + } + const clonedMsg = await this.cloneMsg(msg) + if (clonedMsg) retMsgIds.push(clonedMsg.msgId) } + } else { + retMsgIds = nodeMsgArray.map(msg => msg.msgId) } - if (nodeMsgIds.length === 0) { + if (retMsgIds.length === 0) { throw Error('转发消息失败,节点为空') } - const returnMsg = await this.ctx.ntMsgApi.multiForwardMsg(srcPeer!, destPeer, nodeMsgIds) - returnMsg.msgShortId = MessageUnique.createMsg(destPeer, returnMsg.msgId) + const returnMsg = await this.ctx.ntMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds) + returnMsg.msgShortId = this.ctx.store.createMsgShortId(destPeer, returnMsg.msgId) return returnMsg } } diff --git a/src/onebot11/action/go-cqhttp/SetEssenceMsg.ts b/src/onebot11/action/go-cqhttp/SetEssenceMsg.ts index db11d7a..6bfbc0f 100644 --- a/src/onebot11/action/go-cqhttp/SetEssenceMsg.ts +++ b/src/onebot11/action/go-cqhttp/SetEssenceMsg.ts @@ -1,6 +1,5 @@ import { BaseAction } from '../BaseAction' import { ActionName } from '../types' -import { MessageUnique } from '@/common/utils/messageUnique' interface Payload { message_id: number | string @@ -13,13 +12,13 @@ export class SetEssenceMsg extends BaseAction { if (!payload.message_id) { throw Error('message_id不能为空') } - const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id) + const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id) if (!msg) { throw new Error('msg not found') } return await this.ctx.ntGroupApi.addGroupEssence( - msg.Peer.peerUid, - msg.MsgId + msg.peer.peerUid, + msg.msgId ) } } diff --git a/src/onebot11/action/llonebot/FetchEmojiLike.ts b/src/onebot11/action/llonebot/FetchEmojiLike.ts index 85fdd77..4296801 100644 --- a/src/onebot11/action/llonebot/FetchEmojiLike.ts +++ b/src/onebot11/action/llonebot/FetchEmojiLike.ts @@ -1,6 +1,5 @@ import { BaseAction, Schema } from '../BaseAction' import { ActionName } from '../types' -import { MessageUnique } from '@/common/utils/messageUnique' import { Dict } from 'cosmokit' interface Payload { @@ -20,9 +19,9 @@ export class FetchEmojiLike extends BaseAction { }) async _handle(payload: Payload) { - const msgInfo = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id) + const msgInfo = await this.ctx.store.getMsgInfoByShortId(+payload.message_id) if (!msgInfo) throw new Error('消息不存在') - const { msgSeq } = (await this.ctx.ntMsgApi.getMsgsByMsgId(msgInfo.Peer, [msgInfo.MsgId])).msgList[0] - return await this.ctx.ntMsgApi.getMsgEmojiLikesList(msgInfo.Peer, msgSeq, payload.emojiId, payload.emojiType, +payload.count) + const { msgSeq } = (await this.ctx.ntMsgApi.getMsgsByMsgId(msgInfo.peer, [msgInfo.msgId])).msgList[0] + return await this.ctx.ntMsgApi.getMsgEmojiLikesList(msgInfo.peer, msgSeq, payload.emojiId, payload.emojiType, +payload.count) } } diff --git a/src/onebot11/action/llonebot/GetFriendMsgHistory.ts b/src/onebot11/action/llonebot/GetFriendMsgHistory.ts index 9beee54..87605dd 100644 --- a/src/onebot11/action/llonebot/GetFriendMsgHistory.ts +++ b/src/onebot11/action/llonebot/GetFriendMsgHistory.ts @@ -2,7 +2,6 @@ import { BaseAction, Schema } from '../BaseAction' import { OB11Message } from '@/onebot11/types' import { ActionName } from '../types' import { ChatType, RawMessage } from '@/ntqqapi/types' -import { MessageUnique } from '@/common/utils/messageUnique' import { OB11Entities } from '@/onebot11/entities' import { filterNullable } from '@/common/utils/misc' @@ -32,9 +31,9 @@ export class GetFriendMsgHistory extends BaseAction { const startMsgId = payload.message_seq ?? payload.message_id let msgList: RawMessage[] if (startMsgId) { - const msgInfo = await MessageUnique.getMsgIdAndPeerByShortId(+startMsgId) + const msgInfo = await this.ctx.store.getMsgInfoByShortId(+startMsgId) if (!msgInfo) throw new Error(`消息${startMsgId}不存在`) - msgList = (await this.ctx.ntMsgApi.getMsgHistory(msgInfo.Peer, msgInfo.MsgId, +payload.count)).msgList + msgList = (await this.ctx.ntMsgApi.getMsgHistory(msgInfo.peer, msgInfo.msgId, +payload.count)).msgList } else { const uid = await this.ctx.ntUserApi.getUidByUin(payload.user_id.toString()) if (!uid) throw new Error(`记录${payload.user_id}不存在`) @@ -45,7 +44,7 @@ export class GetFriendMsgHistory extends BaseAction { if (msgList.length === 0) throw new Error('未找到消息') if (payload.reverseOrder) msgList.reverse() msgList.map(msg => { - msg.msgShortId = MessageUnique.createMsg({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId) + msg.msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId) }) const ob11MsgList = await Promise.all(msgList.map(msg => OB11Entities.message(this.ctx, msg))) return { messages: filterNullable(ob11MsgList) } diff --git a/src/onebot11/action/msg/DeleteMsg.ts b/src/onebot11/action/msg/DeleteMsg.ts index 693d6aa..f0befc0 100644 --- a/src/onebot11/action/msg/DeleteMsg.ts +++ b/src/onebot11/action/msg/DeleteMsg.ts @@ -1,6 +1,5 @@ import { ActionName } from '../types' import { BaseAction } from '../BaseAction' -import { MessageUnique } from '@/common/utils/messageUnique' interface Payload { message_id: number | string @@ -13,11 +12,11 @@ class DeleteMsg extends BaseAction { if (!payload.message_id) { throw new Error('参数message_id不能为空') } - const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id) + const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id) if (!msg) { throw new Error(`消息${payload.message_id}不存在`) } - const data = await this.ctx.ntMsgApi.recallMsg(msg.Peer, [msg.MsgId]) + const data = await this.ctx.ntMsgApi.recallMsg(msg.peer, [msg.msgId]) if (data.result !== 0) { this.ctx.logger.error('delete_msg', payload.message_id, data) throw new Error(`消息撤回失败`) diff --git a/src/onebot11/action/msg/ForwardSingleMsg.ts b/src/onebot11/action/msg/ForwardSingleMsg.ts index 8ec616b..ec77a93 100644 --- a/src/onebot11/action/msg/ForwardSingleMsg.ts +++ b/src/onebot11/action/msg/ForwardSingleMsg.ts @@ -2,7 +2,6 @@ import { BaseAction } from '../BaseAction' import { ChatType } from '@/ntqqapi/types' import { ActionName } from '../types' import { Peer } from '@/ntqqapi/types' -import { MessageUnique } from '@/common/utils/messageUnique' interface Payload { message_id: number | string @@ -26,12 +25,12 @@ abstract class ForwardSingleMsg extends BaseAction { if (!payload.message_id) { throw Error('message_id不能为空') } - const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id) + const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id) if (!msg) { throw new Error(`无法找到消息${payload.message_id}`) } const peer = await this.getTargetPeer(payload) - const ret = await this.ctx.ntMsgApi.forwardMsg(msg.Peer, peer, [msg.MsgId]) + const ret = await this.ctx.ntMsgApi.forwardMsg(msg.peer, peer, [msg.msgId]) if (ret.result !== 0) { throw new Error(`转发消息失败 ${ret.errMsg}`) } diff --git a/src/onebot11/action/msg/GetMsg.ts b/src/onebot11/action/msg/GetMsg.ts index 365ea04..1ddf0dd 100644 --- a/src/onebot11/action/msg/GetMsg.ts +++ b/src/onebot11/action/msg/GetMsg.ts @@ -2,7 +2,6 @@ import { BaseAction } from '../BaseAction' import { OB11Message } from '../../types' import { OB11Entities } from '../../entities' import { ActionName } from '../types' -import { MessageUnique } from '@/common/utils/messageUnique' export interface PayloadType { message_id: number | string @@ -17,22 +16,21 @@ class GetMsg extends BaseAction { if (!payload.message_id) { throw new Error('参数message_id不能为空') } - const msgShortId = MessageUnique.getShortIdByMsgId(payload.message_id.toString()) - const msgIdWithPeer = await MessageUnique.getMsgIdAndPeerByShortId(msgShortId || +payload.message_id) - if (!msgIdWithPeer) { + const msgInfo = await this.ctx.store.getMsgInfoByShortId(+payload.message_id) + if (!msgInfo) { throw new Error('消息不存在') } const peer = { guildId: '', - peerUid: msgIdWithPeer.Peer.peerUid, - chatType: msgIdWithPeer.Peer.chatType + peerUid: msgInfo.peer.peerUid, + chatType: msgInfo.peer.chatType } - const msg = this.adapter.getMsgCache(msgIdWithPeer.MsgId) ?? (await this.ctx.ntMsgApi.getMsgsByMsgId(peer, [msgIdWithPeer.MsgId])).msgList[0] + const msg = this.adapter.getMsgCache(msgInfo.msgId) ?? (await this.ctx.ntMsgApi.getMsgsByMsgId(peer, [msgInfo.msgId])).msgList[0] const retMsg = await OB11Entities.message(this.ctx, msg) if (!retMsg) { throw new Error('消息为空') } - retMsg.message_id = MessageUnique.createMsg(peer, msg.msgId)! + retMsg.message_id = this.ctx.store.createMsgShortId(peer, msg.msgId) retMsg.message_seq = retMsg.message_id retMsg.real_id = retMsg.message_id return retMsg diff --git a/src/onebot11/action/msg/SetMsgEmojiLike.ts b/src/onebot11/action/msg/SetMsgEmojiLike.ts index 2f8c694..e6a8360 100644 --- a/src/onebot11/action/msg/SetMsgEmojiLike.ts +++ b/src/onebot11/action/msg/SetMsgEmojiLike.ts @@ -1,6 +1,5 @@ import { ActionName } from '../types' import { BaseAction } from '../BaseAction' -import { MessageUnique } from '@/common/utils/messageUnique' interface Payload { message_id: number | string @@ -14,19 +13,19 @@ export class SetMsgEmojiLike extends BaseAction { if (!payload.message_id) { throw Error('message_id不能为空') } - const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id) + const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id) if (!msg) { throw new Error('msg not found') } if (!payload.emoji_id) { throw new Error('emojiId not found') } - const msgData = (await this.ctx.ntMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId])).msgList + const msgData = (await this.ctx.ntMsgApi.getMsgsByMsgId(msg.peer, [msg.msgId])).msgList if (!msgData || msgData.length == 0 || !msgData[0].msgSeq) { throw new Error('find msg by msgid error') } return await this.ctx.ntMsgApi.setEmojiLike( - msg.Peer, + msg.peer, msgData[0].msgSeq, payload.emoji_id.toString(), true diff --git a/src/onebot11/action/user/SendLike.ts b/src/onebot11/action/user/SendLike.ts index 2eb8551..0dad96d 100644 --- a/src/onebot11/action/user/SendLike.ts +++ b/src/onebot11/action/user/SendLike.ts @@ -10,15 +10,12 @@ export default class SendLike extends BaseAction { actionName = ActionName.SendLike protected async _handle(payload: Payload): Promise { - try { - const qq = payload.user_id.toString() - const uid: string = await this.ctx.ntUserApi.getUidByUin(qq) || '' - const result = await this.ctx.ntUserApi.like(uid, +payload.times || 1) - if (result?.result !== 0) { - throw Error(result?.errMsg) - } - } catch (e) { - throw `点赞失败 ${e}` + const uin = payload.user_id.toString() + const uid = await this.ctx.ntUserApi.getUidByUin(uin) + if (!uid) throw new Error('无法获取用户信息') + const result = await this.ctx.ntUserApi.like(uid, +payload.times || 1) + if (result.result !== 0) { + throw new Error(result.errMsg) } return null } diff --git a/src/onebot11/adapter.ts b/src/onebot11/adapter.ts index 0676bbf..ba28cfe 100644 --- a/src/onebot11/adapter.ts +++ b/src/onebot11/adapter.ts @@ -13,7 +13,6 @@ import { } from '../ntqqapi/types' import { OB11GroupRequestEvent } from './event/request/OB11GroupRequest' import { OB11FriendRequestEvent } from './event/request/OB11FriendRequest' -import { MessageUnique } from '../common/utils/messageUnique' import { GroupDecreaseSubType, OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent' import { selfInfo } from '../common/globalVars' import { OB11Config, Config as LLOBConfig } from '../common/types' @@ -37,7 +36,7 @@ declare module 'cordis' { } class OneBot11Adapter extends Service { - static inject = ['ntMsgApi', 'ntFileApi', 'ntFileCacheApi', 'ntFriendApi', 'ntGroupApi', 'ntUserApi', 'ntWindowApi', 'ntWebApi'] + static inject = ['ntMsgApi', 'ntFileApi', 'ntFileCacheApi', 'ntFriendApi', 'ntGroupApi', 'ntUserApi', 'ntWindowApi', 'ntWebApi', 'store'] public messages: Map = new Map() public startTime = 0 @@ -190,7 +189,7 @@ class OneBot11Adapter extends Service { chatType: message.chatType, peerUid: message.peerUid } - message.msgShortId = MessageUnique.createMsg(peer, message.msgId) + message.msgShortId = this.ctx.store.createMsgShortId(peer, message.msgId) this.addMsgCache(message) OB11Entities.message(this.ctx, message) @@ -227,7 +226,11 @@ class OneBot11Adapter extends Service { } private handleRecallMsg(message: RawMessage) { - const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId) + const peer = { + peerUid: message.peerUid, + chatType: message.chatType + } + const oriMessageId = this.ctx.store.getShortIdByMsgInfo(peer, message.msgId) if (!oriMessageId) { return } diff --git a/src/onebot11/entities.ts b/src/onebot11/entities.ts index 91a6632..dce07bd 100644 --- a/src/onebot11/entities.ts +++ b/src/onebot11/entities.ts @@ -25,7 +25,6 @@ import { } from '../ntqqapi/types' import { EventType } from './event/OB11BaseEvent' import { encodeCQCode } from './cqcode' -import { MessageUnique } from '../common/utils/messageUnique' import { OB11GroupIncreaseEvent } from './event/notice/OB11GroupIncreaseEvent' import { OB11GroupBanEvent } from './event/notice/OB11GroupBanEvent' import { OB11GroupUploadNoticeEvent } from './event/notice/OB11GroupUploadNoticeEvent' @@ -178,7 +177,7 @@ export namespace OB11Entities { messageSegment = { type: OB11MessageDataType.reply, data: { - id: MessageUnique.createMsg(peer, replyMsg ? replyMsg.msgId : records.msgId).toString() + id: ctx.store.createMsgShortId(peer, replyMsg ? replyMsg.msgId : records.msgId).toString() } } } catch (e) { @@ -198,7 +197,7 @@ export namespace OB11Entities { file_size: fileSize, } } - MessageUnique.addFileCache({ + ctx.store.addFileCache({ peerUid: msg.peerUid, msgId: msg.msgId, msgTime: +msg.msgTime, @@ -226,7 +225,7 @@ export namespace OB11Entities { file_size: fileSize, } } - MessageUnique.addFileCache({ + ctx.store.addFileCache({ peerUid: msg.peerUid, msgId: msg.msgId, msgTime: +msg.msgTime, @@ -251,7 +250,7 @@ export namespace OB11Entities { file_size: fileSize, } } - MessageUnique.addFileCache({ + ctx.store.addFileCache({ peerUid: msg.peerUid, msgId: msg.msgId, msgTime: +msg.msgTime, @@ -275,7 +274,7 @@ export namespace OB11Entities { file_size: fileSize, } } - MessageUnique.addFileCache({ + ctx.store.addFileCache({ peerUid: msg.peerUid, msgId: msg.msgId, msgTime: +msg.msgTime, @@ -530,7 +529,7 @@ export namespace OB11Entities { if (!replyMsgList?.length) { return } - const shortId = MessageUnique.getShortIdByMsgId(replyMsgList[0].msgId) + const shortId = ctx.store.getShortIdByMsgInfo(peer, replyMsgList[0].msgId) return new OB11GroupMsgEmojiLikeEvent( parseInt(msg.peerUid), parseInt(senderUin), @@ -581,27 +580,28 @@ export namespace OB11Entities { ) } } - if (grayTipElement.jsonGrayTipElement?.busiId === '2401') { + if (grayTipElement.jsonGrayTipElement?.busiId === '2401' && json.items[2]) { ctx.logger.info('收到群精华消息', json) - const searchParams = new URL(json.items[0].jp).searchParams - const msgSeq = searchParams.get('msgSeq') - const groupCode = searchParams.get('groupCode') - if (!groupCode || !msgSeq) return + const searchParams = new URL(json.items[2].jp).searchParams + const msgSeq = searchParams.get('seq') + const groupCode = searchParams.get('gc') + const msgRandom = searchParams.get('random') + if (!groupCode || !msgSeq || !msgRandom) return const peer = { guildId: '', chatType: ChatType.group, peerUid: groupCode } - const essence = await ctx.ntWebApi.findGroupEssenceMsg(groupCode, +msgSeq) - if (!essence) return - const { msgList } = await ctx.ntMsgApi.queryMsgsWithFilterExBySeq(peer, msgSeq, String(essence.sender_time)) + const essence = await ctx.ntGroupApi.queryCachedEssenceMsg(groupCode, msgSeq, msgRandom) + const { msgList } = await ctx.ntMsgApi.queryMsgsWithFilterExBySeq(peer, msgSeq, '0') + const sourceMsg = msgList.find(e => e.msgRandom === msgRandom) + if (!sourceMsg) return return new OB11GroupEssenceEvent( parseInt(msg.peerUid), - MessageUnique.getShortIdByMsgId(msgList[0].msgId)!, - parseInt(msgList[0].senderUin), - parseInt(essence.add_digest_uin), + ctx.store.getShortIdByMsgInfo(peer, sourceMsg.msgId)!, + parseInt(essence.items[0]?.msgSenderUin ?? sourceMsg.senderUin), + parseInt(essence.items[0]?.opUin ?? '0'), ) - // 获取MsgSeq+Peer可获取具体消息 } if (grayTipElement.jsonGrayTipElement?.busiId === '2407') { const memberUin = json.items[1].param[0] diff --git a/src/onebot11/helper/createMessage.ts b/src/onebot11/helper/createMessage.ts index 43e7fac..7d85ca9 100644 --- a/src/onebot11/helper/createMessage.ts +++ b/src/onebot11/helper/createMessage.ts @@ -16,7 +16,6 @@ import { import { decodeCQCode } from '../cqcode' import { Peer } from '@/ntqqapi/types/msg' import { SendElementEntities } from '@/ntqqapi/entities' -import { MessageUnique } from '@/common/utils/messageUnique' import { selfInfo } from '@/common/globalVars' import { uri2local } from '@/common/utils' import { Context } from 'cordis' @@ -87,14 +86,14 @@ export async function createSendElements( break case OB11MessageDataType.reply: { if (sendMsg.data?.id) { - const replyMsgId = await MessageUnique.getMsgIdAndPeerByShortId(+sendMsg.data.id) + const replyMsgId = await ctx.store.getMsgInfoByShortId(+sendMsg.data.id) if (!replyMsgId) { ctx.logger.warn('回复消息不存在', replyMsgId) continue } const replyMsg = (await ctx.ntMsgApi.getMsgsByMsgId( - replyMsgId.Peer, - [replyMsgId.MsgId!] + replyMsgId.peer, + [replyMsgId.msgId!] )).msgList[0] if (replyMsg) { sendElements.push( @@ -277,7 +276,7 @@ export async function sendMsg( //log('设置消息超时时间', timeout) const returnMsg = await ctx.ntMsgApi.sendMsg(peer, sendElements, timeout) if (returnMsg) { - returnMsg.msgShortId = MessageUnique.createMsg(peer, returnMsg.msgId) + returnMsg.msgShortId = ctx.store.createMsgShortId(peer, returnMsg.msgId) ctx.logger.info('消息发送', returnMsg.msgShortId) deleteAfterSentFiles.map(path => fsPromise.unlink(path)) return returnMsg diff --git a/src/onebot11/helper/quickOperation.ts b/src/onebot11/helper/quickOperation.ts index 1f0973f..913ab19 100644 --- a/src/onebot11/helper/quickOperation.ts +++ b/src/onebot11/helper/quickOperation.ts @@ -3,7 +3,6 @@ import { OB11FriendRequestEvent } from '../event/request/OB11FriendRequest' import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest' import { GroupRequestOperateTypes } from '@/ntqqapi/types' import { convertMessage2List, createSendElements, sendMsg, createPeer, CreatePeerMode } from '../helper/createMessage' -import { MessageUnique } from '@/common/utils/messageUnique' import { isNullable } from 'cosmokit' import { Context } from 'cordis' @@ -88,18 +87,18 @@ async function handleMsg(ctx: Context, msg: OB11Message, quickAction: QuickOpera } if (msg.message_type === 'group') { const groupMsgQuickAction = quickAction as QuickOperationGroupMessage - const rawMessage = await MessageUnique.getMsgIdAndPeerByShortId(+(msg.message_id ?? 0)) + const rawMessage = await ctx.store.getMsgInfoByShortId(+(msg.message_id ?? 0)) if (!rawMessage) return // handle group msg if (groupMsgQuickAction.delete) { - ctx.ntMsgApi.recallMsg(peer, [rawMessage.MsgId]).catch(e => ctx.logger.error(e)) + ctx.ntMsgApi.recallMsg(peer, [rawMessage.msgId]).catch(e => ctx.logger.error(e)) } if (groupMsgQuickAction.kick) { - const { msgList } = await ctx.ntMsgApi.getMsgsByMsgId(peer, [rawMessage.MsgId]) + const { msgList } = await ctx.ntMsgApi.getMsgsByMsgId(peer, [rawMessage.msgId]) ctx.ntGroupApi.kickMember(peer.peerUid, [msgList[0].senderUid]).catch(e => ctx.logger.error(e)) } if (groupMsgQuickAction.ban) { - const { msgList } = await ctx.ntMsgApi.getMsgsByMsgId(peer, [rawMessage.MsgId]) + const { msgList } = await ctx.ntMsgApi.getMsgsByMsgId(peer, [rawMessage.msgId]) ctx.ntGroupApi.banMember(peer.peerUid, [ { uid: msgList[0].senderUid,