diff --git a/src/ntqqapi/api/file.ts b/src/ntqqapi/api/file.ts index 895d81e..22eae3f 100644 --- a/src/ntqqapi/api/file.ts +++ b/src/ntqqapi/api/file.ts @@ -13,15 +13,14 @@ import { PicElement, } from '../types' import path from 'node:path' -import fs from 'node:fs' +import { existsSync } from 'node:fs' import { ReceiveCmdS } from '../hook' import { RkeyManager } from '@/ntqqapi/helper/rkey' import { getSession } from '@/ntqqapi/wrapper' -import { Peer } from '@/ntqqapi/types/msg' +import { OnRichMediaDownloadCompleteParams, Peer } from '@/ntqqapi/types/msg' import { calculateFileMD5 } from '@/common/utils/file' import { fileTypeFromFile } from 'file-type' -import fsPromise from 'node:fs/promises' -import { OnRichMediaDownloadCompleteParams } from '@/ntqqapi/listeners' +import { copyFile, stat, unlink } from 'node:fs/promises' import { Time } from 'cosmokit' import { Service, Context } from 'cordis' import { TEMP_DIR } from '@/common/globalVars' @@ -111,8 +110,8 @@ export class NTQQFileApi extends Service { }, }]) } - await fsPromise.copyFile(filePath, mediaPath) - const fileSize = (await fsPromise.stat(filePath)).size + await copyFile(filePath, mediaPath) + const fileSize = (await stat(filePath)).size return { md5: fileMd5, fileName, @@ -133,10 +132,10 @@ export class NTQQFileApi extends Service { force = false ) { // 用于下载收到的消息中的图片等 - if (sourcePath && fs.existsSync(sourcePath)) { + if (sourcePath && existsSync(sourcePath)) { if (force) { try { - await fsPromise.unlink(sourcePath) + await unlink(sourcePath) } catch { } } else { return sourcePath diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index 1158fe8..0458169 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -1,10 +1,18 @@ import { ReceiveCmdS } from '../hook' -import { Group, GroupMember, GroupMemberRole, GroupNotifies, GroupRequestOperateTypes, GetFileListParam, PublishGroupBulletinReq } from '../types' +import { + Group, + GroupMember, + GroupMemberRole, + GroupNotifies, + GroupRequestOperateTypes, + GetFileListParam, + OnGroupFileInfoUpdateParams, + PublishGroupBulletinReq +} from '../types' import { invoke, NTClass, NTMethod } from '../ntcall' import { GeneralCallResult } from '../services' import { NTQQWindows } from './window' import { getSession } from '../wrapper' -import { OnGroupFileInfoUpdateParams } from '../listeners' import { NodeIKernelGroupService } from '../services' import { Service, Context } from 'cordis' import { isNumeric } from '@/common/utils/misc' diff --git a/src/ntqqapi/listeners/NodeIKernelGroupListener.ts b/src/ntqqapi/listeners/NodeIKernelGroupListener.ts deleted file mode 100644 index 0eb222a..0000000 --- a/src/ntqqapi/listeners/NodeIKernelGroupListener.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Group, GroupListUpdateType, GroupMember, GroupNotify } from '@/ntqqapi/types' - -export interface IGroupListener { - onGroupListUpdate(updateType: GroupListUpdateType, groupList: Group[]): void - - onGroupExtListUpdate(...args: unknown[]): void - - onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void - - onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]): void - - onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void - - onGroupDetailInfoChange(...args: unknown[]): void - - onGroupAllInfoChange(...args: unknown[]): void - - onGroupsMsgMaskResult(...args: unknown[]): void - - onGroupConfMemberChange(...args: unknown[]): void - - onGroupBulletinChange(...args: unknown[]): void - - onGetGroupBulletinListResult(...args: unknown[]): void - - onMemberListChange(arg: { - sceneId: string, - ids: string[], - infos: Map, - finish: boolean, - hasRobot: boolean - }): void - - onMemberInfoChange(groupCode: string, changeType: number, members: Map): void - - onSearchMemberChange(...args: unknown[]): void - - onGroupBulletinRichMediaDownloadComplete(...args: unknown[]): void - - onGroupBulletinRichMediaProgressUpdate(...args: unknown[]): void - - onGroupStatisticInfoChange(...args: unknown[]): void - - onJoinGroupNotify(...args: unknown[]): void - - onShutUpMemberListChanged(...args: unknown[]): void - - onGroupBulletinRemindNotify(...args: unknown[]): void - - onGroupFirstBulletinNotify(...args: unknown[]): void - - onJoinGroupNoVerifyFlag(...args: unknown[]): void - - onGroupArkInviteStateResult(...args: unknown[]): void - - // 发现于Win 9.9.9 23159 - onGroupMemberLevelInfoChange(...args: unknown[]): void -} \ No newline at end of file diff --git a/src/ntqqapi/listeners/NodeIKernelMsgListener.ts b/src/ntqqapi/listeners/NodeIKernelMsgListener.ts deleted file mode 100644 index fd0c8de..0000000 --- a/src/ntqqapi/listeners/NodeIKernelMsgListener.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { ChatType, RawMessage } from '@/ntqqapi/types' - -export interface OnRichMediaDownloadCompleteParams { - fileModelId: string, - msgElementId: string, - msgId: string, - fileId: string, - fileProgress: string, // '0' - fileSpeed: string, // '0' - fileErrCode: string, // '0' - fileErrMsg: string, - fileDownType: number, // 暂时未知 - thumbSize: number, - filePath: string, - totalSize: string, - trasferStatus: number, - step: number, - commonFileInfo: unknown | null, - fileSrvErrCode: string, - clientMsg: string, - businessId: number, - userTotalSpacePerDay: unknown | null, - userUsedSpacePerDay: unknown | null -} - -export interface OnGroupFileInfoUpdateParams { - retCode: number - retMsg: string - clientWording: string - isEnd: boolean - item: { - peerId: string - type: number - folderInfo?: { - folderId: string - parentFolderId: string - folderName: string - createTime: number - modifyTime: number - createUin: string - creatorName: string - totalFileCount: number - modifyUin: string - modifyName: string - usedSpace: string - } - fileInfo?: { - fileModelId: string - fileId: string - fileName: string - fileSize: string - busId: number - uploadedSize: string - uploadTime: number - deadTime: number - modifyTime: number - downloadTimes: number - sha: string - sha3: string - md5: string - uploaderLocalPath: string - uploaderName: string - uploaderUin: string - parentFolderId: string - localPath: string - transStatus: number - transType: number - elementId: string - isFolder: boolean - } - }[] - allFileCount: number - nextIndex: number - reqId: number -} - -// { -// sessionType: 1, -// chatType: 100, -// peerUid: 'u_PVQ3tl6K78xxxx', -// groupCode: '809079648', -// fromNick: '拾xxxx, -// sig: '0x' -// } -export interface TempOnRecvParams { - sessionType: number,//1 - chatType: ChatType,//100 - peerUid: string,//uid - groupCode: string,//gc - fromNick: string,//gc name - sig: string, -} - -export interface IKernelMsgListener { - onAddSendMsg(msgRecord: RawMessage): void - - onBroadcastHelperDownloadComplete(broadcastHelperTransNotifyInfo: unknown): void - - onBroadcastHelperProgressUpdate(broadcastHelperTransNotifyInfo: unknown): void - - onChannelFreqLimitInfoUpdate(contact: unknown, z: unknown, freqLimitInfo: unknown): void - - onContactUnreadCntUpdate(hashMap: unknown): void - - onCustomWithdrawConfigUpdate(customWithdrawConfig: unknown): void - - onDraftUpdate(contact: unknown, arrayList: unknown, j2: unknown): void - - onEmojiDownloadComplete(emojiNotifyInfo: unknown): void - - onEmojiResourceUpdate(emojiResourceInfo: unknown): void - - onFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown): void - - onFileMsgCome(arrayList: unknown): void - - onFirstViewDirectMsgUpdate(firstViewDirectMsgNotifyInfo: unknown): void - - onFirstViewGroupGuildMapping(arrayList: unknown): void - - onGrabPasswordRedBag(i2: unknown, str: unknown, i3: unknown, recvdOrder: unknown, msgRecord: unknown): void - - onGroupFileInfoAdd(groupItem: unknown): void - - onGroupFileInfoUpdate(groupFileListResult: OnGroupFileInfoUpdateParams): void - - onGroupGuildUpdate(groupGuildNotifyInfo: unknown): void - - onGroupTransferInfoAdd(groupItem: unknown): void - - onGroupTransferInfoUpdate(groupFileListResult: unknown): void - - onGuildInteractiveUpdate(guildInteractiveNotificationItem: unknown): void - - onGuildMsgAbFlagChanged(guildMsgAbFlag: unknown): void - - onGuildNotificationAbstractUpdate(guildNotificationAbstractInfo: unknown): void - - onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: unknown): void - - onHitEmojiKeywordResult(hitRelatedEmojiWordsResult: unknown): void - - onHitRelatedEmojiResult(relatedWordEmojiInfo: unknown): void - - onImportOldDbProgressUpdate(importOldDbMsgNotifyInfo: unknown): void - - onInputStatusPush(inputStatusInfo: unknown): void - - onKickedOffLine(kickedInfo: unknown): void - - onLineDev(arrayList: unknown): void - - onLogLevelChanged(j2: unknown): void - - onMsgAbstractUpdate(arrayList: unknown): void - - onMsgBoxChanged(arrayList: unknown): void - - onMsgDelete(contact: unknown, arrayList: unknown): void - - onMsgEventListUpdate(hashMap: unknown): void - - onMsgInfoListAdd(arrayList: unknown): void - - onMsgInfoListUpdate(msgList: RawMessage[]): void - - onMsgQRCodeStatusChanged(i2: unknown): void - - onMsgRecall(i2: unknown, str: unknown, j2: unknown): void - - onMsgSecurityNotify(msgRecord: unknown): void - - onMsgSettingUpdate(msgSetting: unknown): void - - onNtFirstViewMsgSyncEnd(): void - - onNtMsgSyncEnd(): void - - onNtMsgSyncStart(): void - - onReadFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown): void - - onRecvGroupGuildFlag(i2: unknown): void - - onRecvMsg(...arrayList: unknown[]): void - - onRecvMsgSvrRspTransInfo(j2: unknown, contact: unknown, i2: unknown, i3: unknown, str: unknown, bArr: unknown): void - - onRecvOnlineFileMsg(arrayList: unknown): void - - onRecvS2CMsg(arrayList: unknown): void - - onRecvSysMsg(arrayList: unknown): void - - onRecvUDCFlag(i2: unknown): void - - onRichMediaDownloadComplete(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams): void - - onRichMediaProgerssUpdate(fileTransNotifyInfo: unknown): void - - onRichMediaUploadComplete(fileTransNotifyInfo: unknown): void - - onSearchGroupFileInfoUpdate(searchGroupFileResult: - { - result: { - retCode: number, - retMsg: string, - clientWording: string - }, - syncCookie: string, - totalMatchCount: number, - ownerMatchCount: number, - isEnd: boolean, - reqId: number, - item: Array<{ - groupCode: string, - groupName: string, - uploaderUin: string, - uploaderName: string, - matchUin: string, - matchWords: Array, - fileNameHits: Array<{ - start: number, - end: number - }>, - fileModelId: string, - fileId: string, - fileName: string, - fileSize: string, - busId: number, - uploadTime: number, - modifyTime: number, - deadTime: number, - downloadTimes: number, - localPath: string - }> - }): void - - onSendMsgError(j2: unknown, contact: unknown, i2: unknown, str: unknown): void - - onSysMsgNotification(i2: unknown, j2: unknown, j3: unknown, arrayList: unknown): void - - onTempChatInfoUpdate(tempChatInfo: TempOnRecvParams): void - - onUnreadCntAfterFirstView(hashMap: unknown): void - - onUnreadCntUpdate(hashMap: unknown): void - - onUserChannelTabStatusChanged(z: unknown): void - - onUserOnlineStatusChanged(z: unknown): void - - onUserTabStatusChanged(arrayList: unknown): void - - onlineStatusBigIconDownloadPush(i2: unknown, j2: unknown, str: unknown): void - - onlineStatusSmallIconDownloadPush(i2: unknown, j2: unknown, str: unknown): void - - // 第一次发现于Linux - onUserSecQualityChanged(...args: unknown[]): void - - onMsgWithRichLinkInfoUpdate(...args: unknown[]): void - - onRedTouchChanged(...args: unknown[]): void - - // 第一次发现于Win 9.9.9 23159 - onBroadcastHelperProgerssUpdate(...args: unknown[]): void -} \ No newline at end of file diff --git a/src/ntqqapi/listeners/NodeIKernelProfileListener.ts b/src/ntqqapi/listeners/NodeIKernelProfileListener.ts deleted file mode 100644 index 0690815..0000000 --- a/src/ntqqapi/listeners/NodeIKernelProfileListener.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { User, UserDetailInfoListenerArg } from '@/ntqqapi/types' - -export interface IProfileListener { - onProfileSimpleChanged(...args: unknown[]): void - - onUserDetailInfoChanged(arg: UserDetailInfoListenerArg): void - - onProfileDetailInfoChanged(profile: User): void - - onStatusUpdate(...args: unknown[]): void - - onSelfStatusChanged(...args: unknown[]): void - - onStrangerRemarkChanged(...args: unknown[]): void -} \ No newline at end of file diff --git a/src/ntqqapi/listeners/index.ts b/src/ntqqapi/listeners/index.ts deleted file mode 100644 index e0589aa..0000000 --- a/src/ntqqapi/listeners/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './NodeIKernelProfileListener' -export * from './NodeIKernelGroupListener' -export * from './NodeIKernelMsgListener' \ No newline at end of file diff --git a/src/ntqqapi/ntcall.ts b/src/ntqqapi/ntcall.ts index a0f606d..687f208 100644 --- a/src/ntqqapi/ntcall.ts +++ b/src/ntqqapi/ntcall.ts @@ -123,11 +123,15 @@ export function invoke< return new Promise((resolve, reject) => { const apiArgs = [method, ...args] const callbackId = randomUUID() - let success = false + const timeoutId = setTimeout(() => { + log(`ntqq api timeout ${channel}, ${eventName}, ${method}`, apiArgs) + reject(`ntqq api timeout ${channel}, ${eventName}, ${method}, ${apiArgs}`) + }, timeout) + if (!options.cbCmd) { // QQ后端会返回结果,并且可以根据uuid识别 hookApiCallbacks[callbackId] = res => { - success = true + clearTimeout(timeoutId) resolve(res) } } @@ -139,13 +143,13 @@ export function invoke< if (options.cmdCB) { if (options.cmdCB(payload, result)) { removeReceiveHook(hookId) - success = true + clearTimeout(timeoutId) resolve(payload) } } else { removeReceiveHook(hookId) - success = true + clearTimeout(timeoutId) resolve(payload) } }) @@ -158,16 +162,11 @@ export function invoke< } else { log('ntqq api call failed,', method, res) + clearTimeout(timeoutId) reject(`ntqq api call failed, ${method}, ${res.errMsg}`) } } } - setTimeout(() => { - if (!success) { - log(`ntqq api timeout ${channel}, ${eventName}, ${method}`, apiArgs) - reject(`ntqq api timeout ${channel}, ${eventName}, ${method}, ${apiArgs}`) - } - }, timeout) ipcMain.emit( channel, diff --git a/src/ntqqapi/types/msg.ts b/src/ntqqapi/types/msg.ts index 666a755..c9741e6 100644 --- a/src/ntqqapi/types/msg.ts +++ b/src/ntqqapi/types/msg.ts @@ -533,3 +533,77 @@ export interface MessageElement { recommendedMsgElement?: unknown actionBarElement?: unknown } + +export interface OnRichMediaDownloadCompleteParams { + fileModelId: string + msgElementId: string + msgId: string + fileId: string + fileProgress: string // '0' + fileSpeed: string // '0' + fileErrCode: string // '0' + fileErrMsg: string + fileDownType: number // 暂时未知 + thumbSize: number + filePath: string + totalSize: string + trasferStatus: number + step: number + commonFileInfo: unknown + fileSrvErrCode: string + clientMsg: string + businessId: number + userTotalSpacePerDay: unknown + userUsedSpacePerDay: unknown +} + +export interface OnGroupFileInfoUpdateParams { + retCode: number + retMsg: string + clientWording: string + isEnd: boolean + item: { + peerId: string + type: number + folderInfo?: { + folderId: string + parentFolderId: string + folderName: string + createTime: number + modifyTime: number + createUin: string + creatorName: string + totalFileCount: number + modifyUin: string + modifyName: string + usedSpace: string + } + fileInfo?: { + fileModelId: string + fileId: string + fileName: string + fileSize: string + busId: number + uploadedSize: string + uploadTime: number + deadTime: number + modifyTime: number + downloadTimes: number + sha: string + sha3: string + md5: string + uploaderLocalPath: string + uploaderName: string + uploaderUin: string + parentFolderId: string + localPath: string + transStatus: number + transType: number + elementId: string + isFolder: boolean + } + }[] + allFileCount: number + nextIndex: number + reqId: number +} diff --git a/src/ntqqapi/wrapper.ts b/src/ntqqapi/wrapper.ts index fc00750..80fc730 100644 --- a/src/ntqqapi/wrapper.ts +++ b/src/ntqqapi/wrapper.ts @@ -33,30 +33,8 @@ export interface WrapperApi { NodeIQQNTWrapperSession?: NodeIQQNTWrapperSession } -export interface WrapperConstructor { - [key: string]: unknown -} - const wrapperApi: WrapperApi = {} -export const wrapperConstructor: WrapperConstructor = {} - -const constructor = [ - 'NodeIKernelBuddyListener', - 'NodeIKernelGroupListener', - 'NodeQQNTWrapperUtil', - 'NodeIKernelMsgListener', - 'NodeIQQNTWrapperEngine', - 'NodeIGlobalAdapter', - 'NodeIDependsAdapter', - 'NodeIDispatcherAdapter', - 'NodeIKernelSessionListener', - 'NodeIKernelLoginService', - 'NodeIKernelLoginListener', - 'NodeIKernelProfileService', - 'NodeIKernelProfileListener', -] - Process.dlopenOrig = Process.dlopen Process.dlopen = function (module: Dict, filename: string, flags = constants.dlopen.RTLD_LAZY) { @@ -69,9 +47,6 @@ Process.dlopen = function (module: Dict, filename: string, flags = constants.dlo return ret } }) - if (constructor.includes(export_name)) { - wrapperConstructor[export_name] = module.exports[export_name] - } } return dlopenRet } diff --git a/src/onebot11/action/msg/SendMsg.ts b/src/onebot11/action/msg/SendMsg.ts index 4fa0d8f..06ea824 100644 --- a/src/onebot11/action/msg/SendMsg.ts +++ b/src/onebot11/action/msg/SendMsg.ts @@ -31,7 +31,7 @@ export class SendMsg extends BaseAction { payload.auto_escape === true || payload.auto_escape === 'true', ) if (this.getSpecialMsgNum(messages, OB11MessageDataType.node)) { - throw new Error('请使用 /send_group_forward_msg 或 /send_private_forward_msg 发送合并转发') + throw new Error('请使用 /send_group_forward_msg 或 /send_private_forward_msg 进行合并转发') } else if (this.getSpecialMsgNum(messages, OB11MessageDataType.music)) { const music = messages[0] as OB11MessageMusic diff --git a/src/onebot11/entities.ts b/src/onebot11/entities.ts index ad513b3..ca03999 100644 --- a/src/onebot11/entities.ts +++ b/src/onebot11/entities.ts @@ -155,13 +155,21 @@ export namespace OB11Entities { guildId: '' } try { - const { replayMsgSeq, replyMsgTime, senderUidStr } = replyElement + const { replayMsgSeq, replyMsgTime } = replyElement const records = msg.records.find(msgRecord => msgRecord.msgId === replyElement.sourceMsgIdInRecords) - if (!records || !replyMsgTime || !senderUidStr) { + const senderUid = replyElement.senderUidStr || records?.senderUid + if (!records || !replyMsgTime || !senderUid) { throw new Error('找不到回复消息') } - const { msgList } = await ctx.ntMsgApi.queryMsgsWithFilterExBySeq(peer, replayMsgSeq, replyMsgTime, [senderUidStr]) - const replyMsg = msgList.find(msg => msg.msgRandom === records.msgRandom) + const { msgList } = await ctx.ntMsgApi.queryMsgsWithFilterExBySeq(peer, replayMsgSeq, replyMsgTime, [senderUid]) + + let replyMsg: RawMessage | undefined + if (records.msgRandom !== '0') { + replyMsg = msgList.find(msg => msg.msgRandom === records.msgRandom) + } else { + ctx.logger.info('msgRandom is missing', replyElement, records) + replyMsg = msgList[0] + } // 284840486: 合并消息内侧 消息具体定位不到 if (!replyMsg && msg.peerUin !== '284840486') {