From 0d7aa9bd2cac84f27ee890bb631eff15b627e4e3 Mon Sep 17 00:00:00 2001 From: idranme Date: Fri, 16 Aug 2024 21:28:43 +0800 Subject: [PATCH] fix --- src/common/types.ts | 12 ++++ src/common/utils/MessageUnique.ts | 25 +++++--- src/main/main.ts | 16 +++-- src/ntqqapi/api/group.ts | 34 ++++++++++- src/onebot11/action/file/GetFile.ts | 60 +----------------- src/onebot11/action/go-cqhttp/DelGroupFile.ts | 17 ++++++ src/onebot11/action/index.ts | 6 +- src/onebot11/action/types.ts | 1 + src/onebot11/constructor.ts | 61 +++++++++++++------ 9 files changed, 134 insertions(+), 98 deletions(-) create mode 100644 src/onebot11/action/go-cqhttp/DelGroupFile.ts diff --git a/src/common/types.ts b/src/common/types.ts index e7612b4..94987de 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -50,3 +50,15 @@ export interface FileCache { elementId: string elementType: number } + +export interface FileCacheV2 { + fileName: string + fileSize: string + fileUuid: string + msgId: string + msgTime: number + peerUid: string + chatType: number + elementId: string + elementType: number +} \ No newline at end of file diff --git a/src/common/utils/MessageUnique.ts b/src/common/utils/MessageUnique.ts index 9fd3873..27b882e 100644 --- a/src/common/utils/MessageUnique.ts +++ b/src/common/utils/MessageUnique.ts @@ -7,7 +7,7 @@ import SQLite from '@minatojs/driver-sqlite' import fsPromise from 'node:fs/promises' import fs from 'node:fs' import path from 'node:path' -import { FileCache } from '../types' +import { FileCacheV2 } from '../types' interface SQLiteTables extends Tables { message: { @@ -16,7 +16,7 @@ interface SQLiteTables extends Tables { chatType: number peerUid: string } - file: FileCache + file_v2: FileCacheV2 } interface MsgIdAndPeerByShortId { @@ -52,16 +52,19 @@ class MessageUniqueWrapper { }, { primary: 'shortId' }) - database.extend('file', { + 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: 'fileName' + primary: 'fileUuid', + indexes: ['fileName'] }) this.db = database } @@ -142,12 +145,18 @@ class MessageUniqueWrapper { this.msgDataMap.resize(maxSize) } - addFileCache(data: FileCache) { - return this.db?.upsert('file', [data], 'fileName') + addFileCache(data: FileCacheV2) { + return this.db?.upsert('file_v2', [data], 'fileUuid') } - getFileCache(fileName: string) { - return this.db?.get('file', { fileName }) + getFileCacheByName(fileName: string) { + return this.db?.get('file_v2', { fileName }, { + sort: { msgTime: 'desc' } + }) + } + + getFileCacheById(fileUuid: string) { + return this.db?.get('file_v2', { fileUuid }) } } diff --git a/src/main/main.ts b/src/main/main.ts index 1ad1773..5bf644f 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -27,7 +27,7 @@ import { hookNTQQApiCall, hookNTQQApiReceive, ReceiveCmdS, registerReceiveHook, import { OB11Constructor } from '../onebot11/constructor' import { FriendRequestNotify, - GroupNotifies, + GroupNotify, GroupNotifyTypes, RawMessage, BuddyReqType, @@ -244,6 +244,7 @@ function onLoad() { log('report self message error: ', e.stack.toString()) } }) + const processedGroupNotify: string[] = [] registerReceiveHook<{ doubt: boolean oldestUnreadSeq: string @@ -251,26 +252,23 @@ function onLoad() { }>(ReceiveCmdS.UNREAD_GROUP_NOTIFY, async (payload) => { if (payload.unreadCount) { // log("开始获取群通知详情") - let notify: GroupNotifies + let notifies: GroupNotify[] try { - notify = await NTQQGroupApi.getGroupNotifies() + notifies = (await NTQQGroupApi.getSingleScreenNotifies(14)).slice(0, payload.unreadCount) } catch (e) { // log("获取群通知详情失败", e); return } - const notifies = notify.notifies.slice(0, payload.unreadCount) - // log("获取群通知详情完成", notifies, payload); - for (const notify of notifies) { try { notify.time = Date.now() const notifyTime = parseInt(notify.seq) / 1000 - if (notifyTime < startTime) { + const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type + if (notifyTime < startTime || processedGroupNotify.includes(flag)) { continue } - log('收到群通知', notify) - const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type + processedGroupNotify.push(flag) if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) { log('有成员退出通知', notify) const member1Uin = (await NTQQUserApi.getUinByUid(notify.user1.uid))! diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index 3567716..2e39155 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -1,5 +1,5 @@ import { ReceiveCmdS } from '../hook' -import { Group, GroupMember, GroupMemberRole, GroupNotifies, GroupRequestOperateTypes } from '../types' +import { Group, GroupMember, GroupMemberRole, GroupNotifies, GroupRequestOperateTypes, GroupNotify } from '../types' import { callNTQQApi, GeneralCallResult, NTQQApiMethod } from '../ntcall' import { NTQQWindowApi, NTQQWindows } from './window' import { getSession } from '../wrapper' @@ -52,7 +52,7 @@ export class NTQQGroupApi { return groupList } - async getGroupMemberV2(GroupCode: string, uid: string, forced = false) { + static async getGroupMemberV2(GroupCode: string, uid: string, forced = false) { type ListenerType = NodeIKernelGroupListener['onMemberInfoChange'] type EventType = NodeIKernelGroupService['getMemberInfo'] const [, , , _members] = await NTEventDispatch.CallNormalEvent @@ -118,6 +118,36 @@ export class NTQQGroupApi { ) } + static async getSingleScreenNotifies(num: number) { + const [_retData, _doubt, _seq, notifies] = await NTEventDispatch.CallNormalEvent + <(arg1: boolean, arg2: string, arg3: number) => Promise, (doubt: boolean, seq: string, notifies: GroupNotify[]) => void> + ( + 'NodeIKernelGroupService/getSingleScreenNotifies', + 'NodeIKernelGroupListener/onGroupSingleScreenNotifies', + 1, + 5000, + () => true, + false, + '', + num, + ) + return notifies + } + + static async delGroupFile(groupCode: string, files: string[]) { + const session = getSession() + return session?.getRichMediaService().deleteGroupFile(groupCode, [102], files)! + } + + static DelGroupFile = NTQQGroupApi.delGroupFile + + static async delGroupFileFolder(groupCode: string, folderId: string) { + const session = getSession() + return session?.getRichMediaService().deleteGroupFolder(groupCode, folderId)! + } + + static DelGroupFileFolder = NTQQGroupApi.delGroupFileFolder + static async handleGroupRequest(flag: string, operateType: GroupRequestOperateTypes, reason?: string) { const flagitem = flag.split('|') const groupCode = flagitem[0] diff --git a/src/onebot11/action/file/GetFile.ts b/src/onebot11/action/file/GetFile.ts index 11fff91..fbbda7d 100644 --- a/src/onebot11/action/file/GetFile.ts +++ b/src/onebot11/action/file/GetFile.ts @@ -23,66 +23,12 @@ export abstract class GetFileBase extends BaseAction { const { enableLocalFile2Url } = getConfigUtil().getConfig() - let UuidData: { - high: string - low: string - } | undefined - try { - UuidData = UUIDConverter.decode(payload.file) - if (UuidData) { - const peerUin = UuidData.high - const msgId = UuidData.low - const isGroup: boolean = !!(await NTQQGroupApi.getGroups(false)).find(e => e.groupCode == peerUin) - let peer: Peer | undefined - //识别Peer - if (isGroup) { - peer = { chatType: ChatType.group, peerUid: peerUin } - } - const PeerUid = await NTQQUserApi.getUidByUinV2(peerUin) - if (PeerUid) { - const 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') - } - 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 = { - file: downloadPath, - url: downloadPath, - file_size: fileSize, - file_name: fileName, - } - if (enableLocalFile2Url && downloadPath) { - try { - res.base64 = await fsPromise.readFile(downloadPath, 'base64') - } catch (e) { - throw new Error('文件下载失败. ' + e) - } - } - //不手动删除?文件持久化了 - return res - } - } catch { + let fileCache = await MessageUnique.getFileCacheById(String(payload.file)) + if (!fileCache?.length) { + fileCache = await MessageUnique.getFileCacheByName(String(payload.file)) } - const fileCache = await MessageUnique.getFileCache(String(payload.file)) if (fileCache?.length) { const downloadPath = await NTQQFileApi.downloadMedia( fileCache[0].msgId, diff --git a/src/onebot11/action/go-cqhttp/DelGroupFile.ts b/src/onebot11/action/go-cqhttp/DelGroupFile.ts new file mode 100644 index 0000000..581ff4f --- /dev/null +++ b/src/onebot11/action/go-cqhttp/DelGroupFile.ts @@ -0,0 +1,17 @@ +import BaseAction from '../BaseAction' +import { ActionName } from '../types' +import { NTQQGroupApi } from '@/ntqqapi/api' + +interface Payload { + group_id: string | number + file_id: string + busid?: number +} + +export class GoCQHTTPDelGroupFile extends BaseAction { + actionName = ActionName.GoCQHTTP_DelGroupFile + + async _handle(payload: Payload) { + await NTQQGroupApi.delGroupFile(payload.group_id.toString(), [payload.file_id]) + } +} \ No newline at end of file diff --git a/src/onebot11/action/index.ts b/src/onebot11/action/index.ts index a0a8b02..6b6d8d9 100644 --- a/src/onebot11/action/index.ts +++ b/src/onebot11/action/index.ts @@ -1,6 +1,6 @@ import GetMsg from './msg/GetMsg' import GetLoginInfo from './system/GetLoginInfo' -import { GetFriendList, GetFriendWithCategory} from './user/GetFriendList' +import { GetFriendList, GetFriendWithCategory } from './user/GetFriendList' import GetGroupList from './group/GetGroupList' import GetGroupInfo from './group/GetGroupInfo' import GetGroupMemberList from './group/GetGroupMemberList' @@ -53,6 +53,7 @@ import { GoCQHTTHandleQuickOperation } from './go-cqhttp/QuickOperation' import GoCQHTTPSetEssenceMsg from './go-cqhttp/SetEssenceMsg' import GoCQHTTPDelEssenceMsg from './go-cqhttp/DelEssenceMsg' import GetEvent from './llonebot/GetEvent' +import { GoCQHTTPDelGroupFile } from './go-cqhttp/DelGroupFile' export const actionHandlers = [ @@ -113,7 +114,8 @@ export const actionHandlers = [ new GoCQHTTGetForwardMsgAction(), new GoCQHTTHandleQuickOperation(), new GoCQHTTPSetEssenceMsg(), - new GoCQHTTPDelEssenceMsg() + new GoCQHTTPDelEssenceMsg(), + new GoCQHTTPDelGroupFile() ] function initActionMap() { diff --git a/src/onebot11/action/types.ts b/src/onebot11/action/types.ts index 88cdd0f..71730ea 100644 --- a/src/onebot11/action/types.ts +++ b/src/onebot11/action/types.ts @@ -73,4 +73,5 @@ export enum ActionName { GetGroupHonorInfo = "get_group_honor_info", GoCQHTTP_SetEssenceMsg = 'set_essence_msg', GoCQHTTP_DelEssenceMsg = 'delete_essence_msg', + GoCQHTTP_DelGroupFile = 'delete_group_file', } diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index e7982de..2c399cb 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -29,7 +29,6 @@ import { getGroupMember, getSelfUin } from '../common/data' import { EventType } from './event/OB11BaseEvent' import { encodeCQCode } from './cqcode' import { MessageUnique } from '../common/utils/MessageUnique' -import { UUIDConverter } from '../common/utils/helper' import { OB11GroupIncreaseEvent } from './event/notice/OB11GroupIncreaseEvent' import { OB11GroupBanEvent } from './event/notice/OB11GroupBanEvent' import { OB11GroupUploadNoticeEvent } from './event/notice/OB11GroupUploadNoticeEvent' @@ -191,41 +190,61 @@ export class OB11Constructor { }*/ message_data['data']['file'] = picElement.fileName message_data['data']['subType'] = picElement.picSubType - message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId) + //message_data['data']['file_id'] = picElement.fileUuid message_data['data']['url'] = await NTQQFileApi.getImageUrl(picElement) message_data['data']['file_size'] = picElement.fileSize MessageUnique.addFileCache({ peerUid: msg.peerUid, msgId: msg.msgId, + msgTime: +msg.msgTime, chatType: msg.chatType, elementId: element.elementId, elementType: element.elementType, fileName: picElement.fileName, fileSize: String(picElement.fileSize || '0'), + fileUuid: picElement.fileUuid }) } - else if (element.videoElement || element.fileElement) { - const videoOrFileElement = element.videoElement || element.fileElement - message_data['type'] = element.videoElement ? OB11MessageDataType.video : OB11MessageDataType.file - message_data['data']['file'] = videoOrFileElement.fileName - message_data['data']['path'] = videoOrFileElement.filePath - message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId) - message_data['data']['file_size'] = videoOrFileElement.fileSize - if (element.videoElement) { - message_data['data']['url'] = await NTQQFileApi.getVideoUrl({ - chatType: msg.chatType, - peerUid: msg.peerUid, - }, msg.msgId, element.elementId, - ) - } + else if (element.videoElement) { + message_data['type'] = OB11MessageDataType.video + const { videoElement } = element + message_data['data']['file'] = videoElement.fileName + message_data['data']['path'] = videoElement.filePath + //message_data['data']['file_id'] = videoElement.fileUuid + message_data['data']['file_size'] = videoElement.fileSize + message_data['data']['url'] = await NTQQFileApi.getVideoUrl({ + chatType: msg.chatType, + peerUid: msg.peerUid, + }, msg.msgId, element.elementId) MessageUnique.addFileCache({ peerUid: msg.peerUid, msgId: msg.msgId, + msgTime: +msg.msgTime, chatType: msg.chatType, elementId: element.elementId, elementType: element.elementType, - fileName: videoOrFileElement.fileName, - fileSize: String(videoOrFileElement.fileSize || '0') + fileName: videoElement.fileName, + fileSize: String(videoElement.fileSize || '0'), + fileUuid: videoElement.fileUuid! + }) + } + else if (element.fileElement) { + message_data['type'] = OB11MessageDataType.file + const { fileElement } = element + message_data['data']['file'] = fileElement.fileName + message_data['data']['path'] = fileElement.filePath + message_data['data']['file_id'] = fileElement.fileUuid + message_data['data']['file_size'] = fileElement.fileSize + MessageUnique.addFileCache({ + peerUid: msg.peerUid, + msgId: msg.msgId, + msgTime: +msg.msgTime, + chatType: msg.chatType, + elementId: element.elementId, + elementType: element.elementType, + fileName: fileElement.fileName, + fileSize: String(fileElement.fileSize || '0'), + fileUuid: fileElement.fileUuid! }) } else if (element.pttElement) { @@ -233,16 +252,18 @@ export class OB11Constructor { const { pttElement } = element message_data['data']['file'] = pttElement.fileName message_data['data']['path'] = pttElement.filePath - message_data['data']['file_id'] = UUIDConverter.encode(msg.peerUin, msg.msgId) + //message_data['data']['file_id'] = pttElement.fileUuid message_data['data']['file_size'] = pttElement.fileSize MessageUnique.addFileCache({ peerUid: msg.peerUid, msgId: msg.msgId, + msgTime: +msg.msgTime, chatType: msg.chatType, elementId: element.elementId, elementType: element.elementType, fileName: pttElement.fileName, - fileSize: String(pttElement.fileSize || '0') + fileSize: String(pttElement.fileSize || '0'), + fileUuid: pttElement.fileUuid }) } else if (element.arkElement) {