From 1fc02229df33da68b075d71b27db65d3f2db4d30 Mon Sep 17 00:00:00 2001 From: idranme Date: Fri, 9 Aug 2024 15:40:08 +0800 Subject: [PATCH] sync --- package.json | 2 +- src/ntqqapi/api/group.ts | 8 +- src/ntqqapi/api/msg.ts | 72 +- src/ntqqapi/api/user.ts | 4 +- .../listeners/NodeIKernelMsgListener.ts | 514 ++++++++++++ src/ntqqapi/listeners/index.ts | 3 +- src/ntqqapi/services/NodeIKernelMSFService.ts | 3 + src/ntqqapi/services/NodeIKernelMsgService.ts | 744 ++++++++++++++++++ .../services/NodeIKernelUixConvertService.ts | 5 + src/ntqqapi/services/index.ts | 5 +- src/ntqqapi/types/msg.ts | 65 +- src/ntqqapi/wrapper.ts | 8 +- src/onebot11/action/msg/SendMsg.ts | 129 +-- 13 files changed, 1450 insertions(+), 112 deletions(-) create mode 100644 src/ntqqapi/listeners/NodeIKernelMsgListener.ts create mode 100644 src/ntqqapi/services/NodeIKernelMSFService.ts create mode 100644 src/ntqqapi/services/NodeIKernelMsgService.ts create mode 100644 src/ntqqapi/services/NodeIKernelUixConvertService.ts diff --git a/package.json b/package.json index 2f3f21a..ab8026b 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "electron": "^29.0.1", "electron-vite": "^2.3.0", "typescript": "^5.5.4", - "vite": "^5.3.5", + "vite": "^5.4.0", "vite-plugin-cp": "^4.0.8" }, "packageManager": "yarn@4.4.0" diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index 21dc68f..5663862 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -276,8 +276,8 @@ export class NTQQGroupApi { let MsgData = await session?.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false) let param = { groupCode: GroupCode, - msgRandom: parseInt(MsgData.msgList[0].msgRandom), - msgSeq: parseInt(MsgData.msgList[0].msgSeq) + msgRandom: parseInt(MsgData?.msgList[0].msgRandom!), + msgSeq: parseInt(MsgData?.msgList[0].msgSeq!) } // GetMsgByShoretID(ShoretID) -> MsgService.getMsgs(Peer,MsgId,1,false) -> 组出参数 return session?.getGroupService().removeGroupEssence(param) @@ -290,8 +290,8 @@ export class NTQQGroupApi { let MsgData = await session?.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false) let param = { groupCode: GroupCode, - msgRandom: parseInt(MsgData.msgList[0].msgRandom), - msgSeq: parseInt(MsgData.msgList[0].msgSeq) + msgRandom: parseInt(MsgData?.msgList[0].msgRandom!), + msgSeq: parseInt(MsgData?.msgList[0].msgSeq!) } // GetMsgByShoretID(ShoretID) -> MsgService.getMsgs(Peer,MsgId,1,false) -> 组出参数 return session?.getGroupService().addGroupEssence(param) diff --git a/src/ntqqapi/api/msg.ts b/src/ntqqapi/api/msg.ts index 159c158..615eda5 100644 --- a/src/ntqqapi/api/msg.ts +++ b/src/ntqqapi/api/msg.ts @@ -5,8 +5,9 @@ import { selfInfo } from '../../common/data' import { ReceiveCmdS, registerReceiveHook } from '../hook' import { log } from '../../common/utils/log' import { sleep } from '../../common/utils/helper' -import { isQQ998 } from '../../common/utils' +import { isQQ998, getBuildVersion } from '../../common/utils' import { getSession } from '@/ntqqapi/wrapper' +import { NTEventDispatch } from '@/common/utils/EventTask' export let sendMessagePool: Record void) | null> = {} // peerUid: callbackFunc @@ -202,6 +203,9 @@ export class NTQQMsgApi { } static async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) { + if (getBuildVersion() >= 26702) { + return NTQQMsgApi.sendMsgV2(peer, msgElements, waitComplete, timeout) + } const waiter = sendWaiter(peer, waitComplete, timeout) callNTQQApi({ methodName: NTQQApiMethod.SEND_MSG, @@ -218,6 +222,72 @@ export class NTQQMsgApi { return await waiter } + static async sendMsgV2(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) { + if (peer.chatType === ChatType.temp) { + //await NTQQMsgApi.PrepareTempChat().then().catch() + } + function generateMsgId() { + const timestamp = Math.floor(Date.now() / 1000) + const random = Math.floor(Math.random() * Math.pow(2, 32)) + const buffer = Buffer.alloc(8) + buffer.writeUInt32BE(timestamp, 0) + buffer.writeUInt32BE(random, 4) + const msgId = BigInt('0x' + buffer.toString('hex')).toString() + return msgId + } + // 此处有采用Hack方法 利用数据返回正确得到对应消息 + // 与之前 Peer队列 MsgSeq队列 真正的MsgId并发不同 + // 谨慎采用 目前测试暂无问题 Developer.Mlikiowa + let msgId: string + try { + msgId = await NTQQMsgApi.getMsgUnique(peer.chatType, await NTQQMsgApi.getServerTime()) + } catch (error) { + //if (!napCatCore.session.getMsgService()['generateMsgUniqueId']) + //兜底识别策略V2 + msgId = generateMsgId().toString() + } + let data = await NTEventDispatch.CallNormalEvent< + (msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map) => Promise, + (msgList: RawMessage[]) => void + >( + 'NodeIKernelMsgService/sendMsg', + 'NodeIKernelMsgListener/onMsgInfoListUpdate', + 1, + timeout, + (msgRecords: RawMessage[]) => { + for (let msgRecord of msgRecords) { + if (msgRecord.msgId === msgId && msgRecord.sendStatus === 2) { + return true + } + } + return false + }, + msgId, + peer, + msgElements, + new Map() + ) + const retMsg = data[1].find(msgRecord => { + if (msgRecord.msgId === msgId) { + return true + } + }) + return retMsg! + } + + static async getMsgUnique(chatType: number, time: string) { + const session = getSession() + if (getBuildVersion() >= 26702) { + return session?.getMsgService().generateMsgUniqueId(chatType, time)! + } + return session?.getMsgService().getMsgUniqueId(time)! + } + + static async getServerTime() { + const session = getSession() + return session?.getMSFService().getServerTime()! + } + static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) { const waiter = sendWaiter(destPeer, true, 10000) callNTQQApi({ diff --git a/src/ntqqapi/api/user.ts b/src/ntqqapi/api/user.ts index a3803a8..bd8e9d0 100644 --- a/src/ntqqapi/api/user.ts +++ b/src/ntqqapi/api/user.ts @@ -221,7 +221,7 @@ export class NTQQUserApi { static async getUidByUinV1(Uin: string) { const session = getSession() // 通用转换开始尝试 - let uid = (await session?.getUixConvertService().getUid([Uin])).uidInfo.get(Uin); + let uid = (await session?.getUixConvertService().getUid([Uin])!).uidInfo.get(Uin); // Uid 好友转 if (!uid) { friends.forEach((t) => { @@ -255,7 +255,7 @@ export class NTQQUserApi { if (uid) return uid uid = (await session?.getGroupService().getUidByUins([Uin])!).uids.get(Uin) if (uid) return uid - uid = (await session?.getUixConvertService().getUid([Uin])).uidInfo.get(Uin) + uid = (await session?.getUixConvertService().getUid([Uin])!).uidInfo.get(Uin) if (uid) return uid console.log((await NTQQFriendApi.getBuddyIdMapCache(true))) uid = (await NTQQFriendApi.getBuddyIdMapCache(true)).getValue(Uin)//从Buddy缓存获取Uid diff --git a/src/ntqqapi/listeners/NodeIKernelMsgListener.ts b/src/ntqqapi/listeners/NodeIKernelMsgListener.ts new file mode 100644 index 0000000..140714d --- /dev/null +++ b/src/ntqqapi/listeners/NodeIKernelMsgListener.ts @@ -0,0 +1,514 @@ +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 onGroupFileInfoUpdateParamType { + retCode: number + retMsg: string + clientWording: string + isEnd: boolean + item: Array + allFileCount: string + nextIndex: string + reqId: string +} + +// { +// 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: onGroupFileInfoUpdateParamType): 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 + +} + +export interface NodeIKernelMsgListener extends IKernelMsgListener { + // eslint-disable-next-line @typescript-eslint/no-misused-new + new(listener: IKernelMsgListener): NodeIKernelMsgListener +} + + +export class MsgListener implements IKernelMsgListener { + onAddSendMsg(msgRecord: RawMessage) { + + } + + onBroadcastHelperDownloadComplete(broadcastHelperTransNotifyInfo: unknown) { + + } + + onBroadcastHelperProgressUpdate(broadcastHelperTransNotifyInfo: unknown) { + + } + + onChannelFreqLimitInfoUpdate(contact: unknown, z: unknown, freqLimitInfo: unknown) { + + } + + onContactUnreadCntUpdate(hashMap: unknown) { + + } + + onCustomWithdrawConfigUpdate(customWithdrawConfig: unknown) { + + } + + onDraftUpdate(contact: unknown, arrayList: unknown, j2: unknown) { + + } + + onEmojiDownloadComplete(emojiNotifyInfo: unknown) { + + } + + onEmojiResourceUpdate(emojiResourceInfo: unknown) { + + } + + onFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown) { + + } + + onFileMsgCome(arrayList: unknown) { + + } + + onFirstViewDirectMsgUpdate(firstViewDirectMsgNotifyInfo: unknown) { + + } + + onFirstViewGroupGuildMapping(arrayList: unknown) { + + } + + onGrabPasswordRedBag(i2: unknown, str: unknown, i3: unknown, recvdOrder: unknown, msgRecord: unknown) { + + } + + onGroupFileInfoAdd(groupItem: unknown) { + + } + + onGroupFileInfoUpdate(groupFileListResult: onGroupFileInfoUpdateParamType) { + + } + + onGroupGuildUpdate(groupGuildNotifyInfo: unknown) { + + } + + + onGroupTransferInfoAdd(groupItem: unknown) { + + } + + onGroupTransferInfoUpdate(groupFileListResult: unknown) { + + } + + onGuildInteractiveUpdate(guildInteractiveNotificationItem: unknown) { + + } + + onGuildMsgAbFlagChanged(guildMsgAbFlag: unknown) { + + } + + onGuildNotificationAbstractUpdate(guildNotificationAbstractInfo: unknown) { + + } + + onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: unknown) { + + } + + onHitEmojiKeywordResult(hitRelatedEmojiWordsResult: unknown) { + + } + + onHitRelatedEmojiResult(relatedWordEmojiInfo: unknown) { + + } + + onImportOldDbProgressUpdate(importOldDbMsgNotifyInfo: unknown) { + + } + + onInputStatusPush(inputStatusInfo: unknown) { + + } + + onKickedOffLine(kickedInfo: unknown) { + + } + + onLineDev(arrayList: unknown) { + + } + + onLogLevelChanged(j2: unknown) { + + } + + onMsgAbstractUpdate(arrayList: unknown) { + + } + + onMsgBoxChanged(arrayList: unknown) { + + } + + onMsgDelete(contact: unknown, arrayList: unknown) { + + } + + onMsgEventListUpdate(hashMap: unknown) { + + } + + onMsgInfoListAdd(arrayList: unknown) { + + } + + onMsgInfoListUpdate(msgList: RawMessage[]) { + + } + + onMsgQRCodeStatusChanged(i2: unknown) { + + } + + onMsgRecall(i2: unknown, str: unknown, j2: unknown) { + + } + + onMsgSecurityNotify(msgRecord: unknown) { + + } + + onMsgSettingUpdate(msgSetting: unknown) { + + } + + onNtFirstViewMsgSyncEnd() { + + } + + onNtMsgSyncEnd() { + + } + + onNtMsgSyncStart() { + + } + + onReadFeedEventUpdate(firstViewDirectMsgNotifyInfo: unknown) { + + } + + onRecvGroupGuildFlag(i2: unknown) { + + } + + onRecvMsg(arrayList: RawMessage[]) { + + } + + onRecvMsgSvrRspTransInfo(j2: unknown, contact: unknown, i2: unknown, i3: unknown, str: unknown, bArr: unknown) { + + } + + onRecvOnlineFileMsg(arrayList: unknown) { + + } + + onRecvS2CMsg(arrayList: unknown) { + + } + + onRecvSysMsg(arrayList: unknown) { + + } + + onRecvUDCFlag(i2: unknown) { + + } + + onRichMediaDownloadComplete(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams) { + } + + onRichMediaProgerssUpdate(fileTransNotifyInfo: unknown) { + + } + + onRichMediaUploadComplete(fileTransNotifyInfo: unknown) { + + } + + onSearchGroupFileInfoUpdate(searchGroupFileResult: unknown) { + + } + + onSendMsgError(j2: unknown, contact: unknown, i2: unknown, str: unknown) { + + } + + onSysMsgNotification(i2: unknown, j2: unknown, j3: unknown, arrayList: unknown) { + + } + + onTempChatInfoUpdate(tempChatInfo: TempOnRecvParams) { + + } + + onUnreadCntAfterFirstView(hashMap: unknown) { + + } + + onUnreadCntUpdate(hashMap: unknown) { + + } + + onUserChannelTabStatusChanged(z: unknown) { + + } + + onUserOnlineStatusChanged(z: unknown) { + + } + + onUserTabStatusChanged(arrayList: unknown) { + + } + + onlineStatusBigIconDownloadPush(i2: unknown, j2: unknown, str: unknown) { + + } + + onlineStatusSmallIconDownloadPush(i2: unknown, j2: unknown, str: unknown) { + + } + + // 第一次发现于Linux + onUserSecQualityChanged(...args: unknown[]) { + + } + + onMsgWithRichLinkInfoUpdate(...args: unknown[]) { + + } + + onRedTouchChanged(...args: unknown[]) { + + } + // 第一次发现于Win 9.9.9-23159 + onBroadcastHelperProgerssUpdate(...args: unknown[]) { + + } +} \ No newline at end of file diff --git a/src/ntqqapi/listeners/index.ts b/src/ntqqapi/listeners/index.ts index 66fb556..e0589aa 100644 --- a/src/ntqqapi/listeners/index.ts +++ b/src/ntqqapi/listeners/index.ts @@ -1,2 +1,3 @@ export * from './NodeIKernelProfileListener' -export * from './NodeIKernelGroupListener' \ No newline at end of file +export * from './NodeIKernelGroupListener' +export * from './NodeIKernelMsgListener' \ No newline at end of file diff --git a/src/ntqqapi/services/NodeIKernelMSFService.ts b/src/ntqqapi/services/NodeIKernelMSFService.ts new file mode 100644 index 0000000..f0bff51 --- /dev/null +++ b/src/ntqqapi/services/NodeIKernelMSFService.ts @@ -0,0 +1,3 @@ +export interface NodeIKernelMSFService { + getServerTime(): string +} \ No newline at end of file diff --git a/src/ntqqapi/services/NodeIKernelMsgService.ts b/src/ntqqapi/services/NodeIKernelMsgService.ts new file mode 100644 index 0000000..f9a85a9 --- /dev/null +++ b/src/ntqqapi/services/NodeIKernelMsgService.ts @@ -0,0 +1,744 @@ +import { ElementType, MessageElement, Peer, RawMessage, SendMessageElement } from '@/ntqqapi/types' +import { NodeIKernelMsgListener } from '@/ntqqapi/listeners/NodeIKernelMsgListener' +import { GeneralCallResult } from './common' + +export interface QueryMsgsParams { + chatInfo: Peer, + filterMsgType: [], + filterSendersUid: string[], + filterMsgFromTime: string, + filterMsgToTime: string, + pageLimit: number, + isReverseOrder: boolean, + isIncludeCurrent: boolean +} + +export interface TmpChatInfoApi { + errMsg: string + result: number + tmpChatInfo?: TmpChatInfo +} + +export interface TmpChatInfo { + chatType: number + fromNick: string + groupCode: string + peerUid: string + sessionType: number + sig: string +} + +export interface NodeIKernelMsgService { + + generateMsgUniqueId(chatType: number, time: string): string + + addKernelMsgListener(nodeIKernelMsgListener: NodeIKernelMsgListener): number + + sendMsg(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map): Promise + + recallMsg(peer: Peer, msgIds: string[]): Promise + + addKernelMsgImportToolListener(arg: Object): unknown + + removeKernelMsgListener(args: unknown): unknown + + addKernelTempChatSigListener(...args: unknown[]): unknown + + removeKernelTempChatSigListener(...args: unknown[]): unknown + + setAutoReplyTextList(AutoReplyText: Array, i2: number): unknown + + getAutoReplyTextList(...args: unknown[]): unknown + + getOnLineDev(): void + + kickOffLine(DevInfo: Object): unknown + + setStatus(args: { status: number, extStatus: number, batteryStatus: number }): Promise + + fetchStatusMgrInfo(): unknown + + fetchStatusUnitedConfigInfo(): unknown + + getOnlineStatusSmallIconBasePath(): unknown + + getOnlineStatusSmallIconFileNameByUrl(Url: string): unknown + + downloadOnlineStatusSmallIconByUrl(arg0: number, arg1: string): unknown + + getOnlineStatusBigIconBasePath(): unknown + + downloadOnlineStatusBigIconByUrl(arg0: number, arg1: string): unknown + + getOnlineStatusCommonPath(arg: string): unknown + + getOnlineStatusCommonFileNameByUrl(Url: string): unknown + + downloadOnlineStatusCommonByUrl(arg0: string, arg1: string): unknown + + // this.tokenType = i2 + // this.apnsToken = bArr + // this.voipToken = bArr2 + // this.profileId = str + + setToken(arg: Object): unknown + + switchForeGround(): unknown + + switchBackGround(arg: Object): unknown + + //hex + setTokenForMqq(token: string): unknown + + switchForeGroundForMqq(...args: unknown[]): unknown + + switchBackGroundForMqq(...args: unknown[]): unknown + + getMsgSetting(...args: unknown[]): unknown + + setMsgSetting(...args: unknown[]): unknown + + addSendMsg(...args: unknown[]): unknown + + cancelSendMsg(...args: unknown[]): unknown + + switchToOfflineSendMsg(peer: Peer, MsgId: string): unknown + + reqToOfflineSendMsg(...args: unknown[]): unknown + + refuseReceiveOnlineFileMsg(peer: Peer, MsgId: string): unknown + + resendMsg(...args: unknown[]): unknown + + recallMsg(...args: unknown[]): unknown + + reeditRecallMsg(...args: unknown[]): unknown + //调用请检查除开commentElements其余参数不能为null + forwardMsg(msgIds: string[], srcContact: Peer, dstContacts: Peer[], commentElements: MessageElement[]): Promise + + forwardMsgWithComment(...args: unknown[]): unknown + + forwardSubMsgWithComment(...args: unknown[]): unknown + + forwardRichMsgInVist(...args: unknown[]): unknown + + forwardFile(...args: unknown[]): unknown + //Array, Peer from, Peer to + multiForwardMsg(...args: unknown[]): unknown + + multiForwardMsgWithComment(...args: unknown[]): unknown + + deleteRecallMsg(...args: unknown[]): unknown + + deleteRecallMsgForLocal(...args: unknown[]): unknown + + addLocalGrayTipMsg(...args: unknown[]): unknown + + addLocalJsonGrayTipMsg(...args: unknown[]): unknown + + addLocalJsonGrayTipMsgExt(...args: unknown[]): unknown + + IsLocalJsonTipValid(...args: unknown[]): unknown + + addLocalAVRecordMsg(...args: unknown[]): unknown + + addLocalTofuRecordMsg(...args: unknown[]): unknown + + addLocalRecordMsg(Peer: Peer, msgId: string, ele: MessageElement, attr: Array | number, front: boolean): Promise + + deleteMsg(Peer: Peer, msgIds: Array): Promise + + updateElementExtBufForUI(...args: unknown[]): unknown + + updateMsgRecordExtPbBufForUI(...args: unknown[]): unknown + + startMsgSync(...args: unknown[]): unknown + + startGuildMsgSync(...args: unknown[]): unknown + + isGuildChannelSync(...args: unknown[]): unknown + + getMsgUniqueId(UniqueId: string): string + + isMsgMatched(...args: unknown[]): unknown + + getOnlineFileMsgs(...args: unknown[]): unknown + + getAllOnlineFileMsgs(...args: unknown[]): unknown + + getLatestDbMsgs(peer: Peer, cnt: number): Promise + + getLastMessageList(peer: Peer[]): Promise + + getAioFirstViewLatestMsgs(peer: Peer, num: number): unknown + + //deprecated 从9.9.15-26702版本开始,该接口已经废弃,请使用getMsgsEx + getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise + + getMsgsIncludeSelf(peer: Peer, msgId: string, count: number, queryOrder: boolean): Promise + + // this.$peer = contact + // this.$msgTime = j2 + // this.$clientSeq = j3 + // this.$cnt = i2 + + getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise + + getMsgsWithStatus(params: { + peer: Peer + msgId: string + msgTime: unknown + cnt: unknown + queryOrder: boolean + isIncludeSelf: boolean + appid: unknown + }): Promise + + getMsgsBySeqRange(peer: Peer, startSeq: string, endSeq: string): Promise + + getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, unknownArg: boolean): Promise + + getMsgsByMsgId(peer: Peer, ids: string[]): Promise + + getRecallMsgsByMsgId(peer: Peer, MsgId: string[]): Promise + + getMsgsBySeqList(peer: Peer, seqList: string[]): Promise + + getSingleMsg(Peer: Peer, msgSeq: string): Promise + + getSourceOfReplyMsg(peer: Peer, MsgId: string, SourceSeq: string): unknown + + getSourceOfReplyMsgV2(peer: Peer, RootMsgId: string, ReplyMsgId: string): unknown + + getMsgByClientSeqAndTime(peer: Peer, clientSeq: string, time: string): unknown + + getSourceOfReplyMsgByClientSeqAndTime(peer: Peer, clientSeq: string, time: string): unknown + //cnt clientSeq?并不是吧 + getMsgsByTypeFilter(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilter: { type: number, subtype: Array }): unknown + + getMsgsByTypeFilters(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilters: Array<{ type: number, subtype: Array }>): unknown + + getMsgWithAbstractByFilterParam(...args: unknown[]): unknown + + queryMsgsWithFilter(...args: unknown[]): unknown + + /** + * @deprecated 该函数已被标记为废弃,请使用新的替代方法。 + * 使用过滤条件查询消息列表的版本2接口。 + * + * 该函数通过一系列过滤条件来查询特定聊天中的消息列表。这些条件包括消息类型、发送者、时间范围等。 + * 函数返回一个Promise,解析为查询结果的未知类型对象。 + * + * @param MsgId 消息ID,用于特定消息的查询。 + * @param MsgTime 消息时间,用于指定消息的时间范围。 + * @param param 查询参数对象,包含详细的过滤条件和分页信息。 + * @param param.chatInfo 聊天信息,包括聊天类型和对方用户ID。 + * @param param.filterMsgType 需要过滤的消息类型数组,留空表示不过滤。 + * @param param.filterSendersUid 需要过滤的发送者用户ID数组。 + * @param param.filterMsgFromTime 查询消息的起始时间。 + * @param param.filterMsgToTime 查询消息的结束时间。 + * @param param.pageLimit 每页的消息数量限制。 + * @param param.isReverseOrder 是否按时间顺序倒序返回消息。 + * @param param.isIncludeCurrent 是否包含当前页码。 + * @returns 返回一个Promise,解析为查询结果的未知类型对象。 + */ + queryMsgsWithFilterVer2(MsgId: string, MsgTime: string, param: QueryMsgsParams): Promise + + // this.chatType = i2 + // this.peerUid = str + + // this.chatInfo = new ChatInfo() + // this.filterMsgType = new ArrayList<>() + // this.filterSendersUid = new ArrayList<>() + // this.chatInfo = chatInfo + // this.filterMsgType = arrayList + // this.filterSendersUid = arrayList2 + // this.filterMsgFromTime = j2 + // this.filterMsgToTime = j3 + // this.pageLimit = i2 + // this.isReverseOrder = z + // this.isIncludeCurrent = z2 + //queryMsgsWithFilterEx(0L, 0L, 0L, new QueryMsgsParams(new ChatInfo(2, str), new ArrayList(), new ArrayList(), 0L, 0L, 250, false, true)) + queryMsgsWithFilterEx(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): Promise + //queryMsgsWithFilterEx(this.$msgId, this.$msgTime, this.$msgSeq, this.$param) + queryFileMsgsDesktop(...args: unknown[]): unknown + + setMsgRichInfoFlag(...args: unknown[]): unknown + + queryPicOrVideoMsgs(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): Promise + + queryPicOrVideoMsgsDesktop(...args: unknown[]): unknown + + queryEmoticonMsgs(msgId: string, msgTime: string, msgSeq: string, Params: QueryMsgsParams): Promise + + queryTroopEmoticonMsgs(msgId: string, msgTime: string, msgSeq: string, Params: QueryMsgsParams): Promise + + queryMsgsAndAbstractsWithFilter(msgId: string, msgTime: string, megSeq: string, param: QueryMsgsParams): unknown + + setFocusOnGuild(...args: unknown[]): unknown + + setFocusSession(...args: unknown[]): unknown + + enableFilterUnreadInfoNotify(...args: unknown[]): unknown + + enableFilterMsgAbstractNotify(...args: unknown[]): unknown + + onScenesChangeForSilenceMode(...args: unknown[]): unknown + + getContactUnreadCnt(...args: unknown[]): unknown + + getUnreadCntInfo(...args: unknown[]): unknown + + getGuildUnreadCntInfo(...args: unknown[]): unknown + + getGuildUnreadCntTabInfo(...args: unknown[]): unknown + + getAllGuildUnreadCntInfo(...args: unknown[]): unknown + + getAllJoinGuildCnt(...args: unknown[]): unknown + + getAllDirectSessionUnreadCntInfo(...args: unknown[]): unknown + + getCategoryUnreadCntInfo(...args: unknown[]): unknown + + getGuildFeedsUnreadCntInfo(...args: unknown[]): unknown + + setUnVisibleChannelCntInfo(...args: unknown[]): unknown + + setUnVisibleChannelTypeCntInfo(...args: unknown[]): unknown + + setVisibleGuildCntInfo(...args: unknown[]): unknown + + setMsgRead(peer: Peer): Promise + + setAllC2CAndGroupMsgRead(): Promise + + setGuildMsgRead(...args: unknown[]): unknown + + setAllGuildMsgRead(...args: unknown[]): unknown + + setMsgReadAndReport(...args: unknown[]): unknown + + setSpecificMsgReadAndReport(...args: unknown[]): unknown + + setLocalMsgRead(...args: unknown[]): unknown + + setGroupGuildMsgRead(...args: unknown[]): unknown + + getGuildGroupTransData(...args: unknown[]): unknown + + setGroupGuildBubbleRead(...args: unknown[]): unknown + + getGuildGroupBubble(...args: unknown[]): unknown + + fetchGroupGuildUnread(...args: unknown[]): unknown + + setGroupGuildFlag(...args: unknown[]): unknown + + setGuildUDCFlag(...args: unknown[]): unknown + + setGuildTabUserFlag(...args: unknown[]): unknown + + setBuildMode(flag: number/*0 1 3*/): unknown + + setConfigurationServiceData(...args: unknown[]): unknown + + setMarkUnreadFlag(...args: unknown[]): unknown + + getChannelEventFlow(...args: unknown[]): unknown + + getMsgEventFlow(...args: unknown[]): unknown + + getRichMediaFilePathForMobileQQSend(...args: unknown[]): unknown + + getRichMediaFilePathForGuild(arg: { + md5HexStr: string, + fileName: string, + elementType: ElementType, + elementSubType: number, + thumbSize: 0, + needCreate: true, + downloadType: 1, + file_uuid: '' + }): string + + assembleMobileQQRichMediaFilePath(...args: unknown[]): unknown + + getFileThumbSavePathForSend(...args: unknown[]): unknown + + getFileThumbSavePath(...args: unknown[]): unknown + //猜测居多 + translatePtt2Text(MsgId: string, Peer: {}, MsgElement: {}): unknown + + setPttPlayedState(...args: unknown[]): unknown + // NodeIQQNTWrapperSession fetchFavEmojiList [ + // "", + // 48, + // true, + // true + // ] + fetchFavEmojiList(str: string, num: number, uk1: boolean, uk2: boolean): Promise + }> + + addFavEmoji(...args: unknown[]): unknown + + fetchMarketEmoticonList(...args: unknown[]): unknown + + fetchMarketEmoticonShowImage(...args: unknown[]): unknown + + fetchMarketEmoticonAioImage(...args: unknown[]): unknown + + fetchMarketEmotionJsonFile(...args: unknown[]): unknown + + getMarketEmoticonPath(...args: unknown[]): unknown + + getMarketEmoticonPathBySync(...args: unknown[]): unknown + + fetchMarketEmoticonFaceImages(...args: unknown[]): unknown + + fetchMarketEmoticonAuthDetail(...args: unknown[]): unknown + + getFavMarketEmoticonInfo(...args: unknown[]): unknown + + addRecentUsedFace(...args: unknown[]): unknown + + getRecentUsedFaceList(...args: unknown[]): unknown + + getMarketEmoticonEncryptKeys(...args: unknown[]): unknown + + downloadEmojiPic(...args: unknown[]): unknown + + deleteFavEmoji(...args: unknown[]): unknown + + modifyFavEmojiDesc(...args: unknown[]): unknown + + queryFavEmojiByDesc(...args: unknown[]): unknown + + getHotPicInfoListSearchString(...args: unknown[]): unknown + + getHotPicSearchResult(...args: unknown[]): unknown + + getHotPicHotWords(...args: unknown[]): unknown + + getHotPicJumpInfo(...args: unknown[]): unknown + + getEmojiResourcePath(...args: unknown[]): unknown + + JoinDragonGroupEmoji(JoinDragonGroupEmojiReq: any/*joinDragonGroupEmojiReq*/): unknown + + getMsgAbstracts(...args: unknown[]): unknown + + getMsgAbstract(...args: unknown[]): unknown + + getMsgAbstractList(...args: unknown[]): unknown + + getMsgAbstractListBySeqRange(...args: unknown[]): unknown + + refreshMsgAbstracts(...args: unknown[]): unknown + + refreshMsgAbstractsByGuildIds(...args: unknown[]): unknown + + getRichMediaElement(...args: unknown[]): unknown + + cancelGetRichMediaElement(...args: unknown[]): unknown + + refuseGetRichMediaElement(...args: unknown[]): unknown + + switchToOfflineGetRichMediaElement(...args: unknown[]): unknown + + downloadRichMedia(...args: unknown[]): unknown + + getFirstUnreadMsgSeq(args: { + peerUid: string + guildId: string + }): unknown + + getFirstUnreadCommonMsg(...args: unknown[]): unknown + + getFirstUnreadAtmeMsg(...args: unknown[]): unknown + + getFirstUnreadAtallMsg(...args: unknown[]): unknown + + getNavigateInfo(...args: unknown[]): unknown + + getChannelFreqLimitInfo(...args: unknown[]): unknown + + getRecentUseEmojiList(...args: unknown[]): unknown + + getRecentEmojiList(...args: unknown[]): unknown + + setMsgEmojiLikes(...args: unknown[]): unknown + + getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, cookie: string, bForward: boolean, number: number): Promise<{ + result: number, + errMsg: string, + emojiLikesList: + Array<{ + tinyId: string, + nickName: string, + headUrl: string + }>, + cookie: string, + isLastPage: boolean, + isFirstPage: boolean + }> + + setMsgEmojiLikesForRole(...args: unknown[]): unknown + + clickInlineKeyboardButton(...args: unknown[]): unknown + + setCurOnScreenMsg(...args: unknown[]): unknown + + setCurOnScreenMsgForMsgEvent(...args: unknown[]): unknown + + getMiscData(key: string): unknown + + setMiscData(key: string, value: string): unknown + + getBookmarkData(...args: unknown[]): unknown + + setBookmarkData(...args: unknown[]): unknown + + sendShowInputStatusReq(ChatType: number, EventType: number, toUid: string): Promise + + queryCalendar(...args: unknown[]): unknown + + queryFirstMsgSeq(peer: Peer, ...args: unknown[]): unknown + + queryRoamCalendar(...args: unknown[]): unknown + + queryFirstRoamMsg(...args: unknown[]): unknown + + fetchLongMsg(peer: Peer, msgId: string): unknown + + fetchLongMsgWithCb(...args: unknown[]): unknown + + setIsStopKernelFetchLongMsg(...args: unknown[]): unknown + + insertGameResultAsMsgToDb(...args: unknown[]): unknown + + getMultiMsg(...args: unknown[]): Promise + + setDraft(...args: unknown[]): unknown + + getDraft(...args: unknown[]): unknown + + deleteDraft(...args: unknown[]): unknown + + getRecentHiddenSesionList(...args: unknown[]): unknown + + setRecentHiddenSession(...args: unknown[]): unknown + + delRecentHiddenSession(...args: unknown[]): unknown + + getCurHiddenSession(...args: unknown[]): unknown + + setCurHiddenSession(...args: unknown[]): unknown + + setReplyDraft(...args: unknown[]): unknown + + getReplyDraft(...args: unknown[]): unknown + + deleteReplyDraft(...args: unknown[]): unknown + + getFirstUnreadAtMsg(peer: Peer): unknown + + clearMsgRecords(...args: unknown[]): unknown//设置已读后调用我觉得比较好 清理记录 现在别了 + + IsExistOldDb(...args: unknown[]): unknown + + canImportOldDbMsg(...args: unknown[]): unknown + + setPowerStatus(z: boolean): unknown + + canProcessDataMigration(...args: unknown[]): unknown + + importOldDbMsg(...args: unknown[]): unknown + + stopImportOldDbMsgAndroid(...args: unknown[]): unknown + + isMqqDataImportFinished(...args: unknown[]): unknown + + getMqqDataImportTableNames(...args: unknown[]): unknown + + getCurChatImportStatusByUin(...args: unknown[]): unknown + + getDataImportUserLevel(): unknown + + getMsgQRCode(...args: unknown[]): unknown + + getGuestMsgAbstracts(...args: unknown[]): unknown + + getGuestMsgByRange(...args: unknown[]): unknown + + getGuestMsgAbstractByRange(...args: unknown[]): unknown + + registerSysMsgNotification(...args: unknown[]): unknown + + unregisterSysMsgNotification(...args: unknown[]): unknown + + enterOrExitAio(...args: unknown[]): unknown + + // this.peerUid = "" + // this.peerNickname = "" + // this.fromGroupCode = "" + // this.sig = new byte[0] + // this.selfUid = "" + // this.selfPhone = "" + // this.chatType = i2 + // this.peerUid = str + // this.peerNickname = str2 + // this.fromGroupCode = str3 + // this.sig = bArr + // this.selfUid = str4 + // this.selfPhone = str5 + // this.gameSession = tempChatGameSession + prepareTempChat(args: unknown): unknown//主动临时消息 不做 + + sendSsoCmdReqByContend(cmd: string, param: string): Promise + + //chattype,uid->Promise + getTempChatInfo(ChatType: number, Uid: string): Promise + + setContactLocalTop(...args: unknown[]): unknown + + switchAnonymousChat(...args: unknown[]): unknown + + renameAnonyChatNick(...args: unknown[]): unknown + + getAnonymousInfo(...args: unknown[]): unknown + + updateAnonymousInfo(...args: unknown[]): unknown + + sendSummonMsg(peer: Peer, MsgElement: unknown, MsgAttributeInfo: unknown): Promise//频道的东西 + + outputGuildUnreadInfo(...args: unknown[]): unknown + + checkMsgWithUrl(...args: unknown[]): unknown + + checkTabListStatus(...args: unknown[]): unknown + + getABatchOfContactMsgBoxInfo(...args: unknown[]): unknown + + insertMsgToMsgBox(peer: Peer, msgId: string, arg: 2006): unknown + + isHitEmojiKeyword(...args: unknown[]): unknown + + getKeyWordRelatedEmoji(...args: unknown[]): unknown + + recordEmoji(...args: unknown[]): unknown + + fetchGetHitEmotionsByWord(args: Object): Promise//表情推荐? + + deleteAllRoamMsgs(...args: unknown[]): unknown//漫游消息? + + packRedBag(...args: unknown[]): unknown + + grabRedBag(...args: unknown[]): unknown + + pullDetail(...args: unknown[]): unknown + + selectPasswordRedBag(...args: unknown[]): unknown + + pullRedBagPasswordList(...args: unknown[]): unknown + + requestTianshuAdv(...args: unknown[]): unknown + + tianshuReport(...args: unknown[]): unknown + + tianshuMultiReport(...args: unknown[]): unknown + + GetMsgSubType(a0: number, a1: number): unknown + + setIKernelPublicAccountAdapter(...args: unknown[]): unknown + //tempChatGameSession有关 + createUidFromTinyId(fromTinyId: string, toTinyId: string): unknown + + dataMigrationGetDataAvaiableContactList(...args: unknown[]): unknown + + dataMigrationGetMsgList(...args: unknown[]): unknown + + dataMigrationStopOperation(...args: unknown[]): unknown + + //新的希望 + dataMigrationImportMsgPbRecord(DataMigrationMsgInfo: Array<{ + extensionData: string//"Hex" + extraData: string //"" + chatType: number + chatUin: string + msgType: number + msgTime: string + msgSeq: string + msgRandom: string + }>, DataMigrationResourceInfo: { + extraData: string + filePath: string + fileSize: string + msgRandom: string + msgSeq: string + msgSubType: number + msgType: number + }): unknown + + dataMigrationGetResourceLocalDestinyPath(...args: unknown[]): unknown + + dataMigrationSetIOSPathPrefix(...args: unknown[]): unknown + + getServiceAssistantSwitch(...args: unknown[]): unknown + + setServiceAssistantSwitch(...args: unknown[]): unknown + + setSubscribeFolderUsingSmallRedPoint(...args: unknown[]): unknown + + clearGuildNoticeRedPoint(...args: unknown[]): unknown + + clearFeedNoticeRedPoint(...args: unknown[]): unknown + + clearFeedSquareRead(...args: unknown[]): unknown + + IsC2CStyleChatType(...args: unknown[]): unknown + + IsTempChatType(uin: number): unknown//猜的 + + getGuildInteractiveNotification(...args: unknown[]): unknown + + getGuildNotificationAbstract(...args: unknown[]): unknown + + setFocusOnBase(...args: unknown[]): unknown + + queryArkInfo(...args: unknown[]): unknown + + queryUserSecQuality(...args: unknown[]): unknown + + getGuildMsgAbFlag(...args: unknown[]): unknown + + getGroupMsgStorageTime(): unknown//这是嘛啊 + +} \ No newline at end of file diff --git a/src/ntqqapi/services/NodeIKernelUixConvertService.ts b/src/ntqqapi/services/NodeIKernelUixConvertService.ts new file mode 100644 index 0000000..e98749d --- /dev/null +++ b/src/ntqqapi/services/NodeIKernelUixConvertService.ts @@ -0,0 +1,5 @@ +export interface NodeIKernelUixConvertService { + getUin(uid: string[]): Promise<{ uinInfo: Map }> + + getUid(uin: string[]): Promise<{ uidInfo: Map }> +} \ No newline at end of file diff --git a/src/ntqqapi/services/index.ts b/src/ntqqapi/services/index.ts index 052026d..88079a8 100644 --- a/src/ntqqapi/services/index.ts +++ b/src/ntqqapi/services/index.ts @@ -1,4 +1,7 @@ export * from './NodeIKernelBuddyService' export * from './NodeIKernelProfileService' export * from './NodeIKernelGroupService' -export * from './NodeIKernelProfileLikeService' \ No newline at end of file +export * from './NodeIKernelProfileLikeService' +export * from './NodeIKernelMsgService' +export * from './NodeIKernelMSFService' +export * from './NodeIKernelUixConvertService' \ No newline at end of file diff --git a/src/ntqqapi/types/msg.ts b/src/ntqqapi/types/msg.ts index c4c3c2f..c7c7a02 100644 --- a/src/ntqqapi/types/msg.ts +++ b/src/ntqqapi/types/msg.ts @@ -15,13 +15,7 @@ export enum ElementType { export interface SendTextElement { elementType: ElementType.TEXT elementId: '' - textElement: { - content: string - atType: number - atUid: string - atTinyId: string - atNtUid: string - } + textElement: TextElement } export interface SendPttElement { @@ -77,12 +71,7 @@ export interface SendPicElement { export interface SendReplyElement { elementType: ElementType.REPLY elementId: '' - replyElement: { - replayMsgSeq: string - replayMsgId: string - senderUin: string - senderUinStr: string - } + replyElement: ReplyElement } export interface SendFaceElement { @@ -96,6 +85,21 @@ export interface SendMarketFaceElement { marketFaceElement: MarketFaceElement } +export interface TextElement { + content: string + atType: number + atUid: string + atTinyId: string + atNtUid: string +} + +export interface ReplyElement { + replayMsgSeq: string + replayMsgId: string + senderUin: string + senderUinStr: string +} + export interface FileElement { fileMd5?: '' fileName: string @@ -377,6 +381,7 @@ export interface RawMessage { msgShortId?: number // 自己维护的消息id msgTime: string // 时间戳,秒 msgSeq: string + msgRandom: string senderUid: string senderUin?: string // 发送者QQ号 peerUid: string // 群号 或者 QQ uid @@ -419,4 +424,38 @@ export interface Peer { chatType: ChatType peerUid: string // 如果是群聊uid为群号,私聊uid就是加密的字符串 guildId?: string +} + +export interface MessageElement { + elementType: ElementType + elementId: string + extBufForUI: string //"0x" + textElement?: TextElement + faceElement?: FaceElement + marketFaceElement?: MarkdownElement + replyElement?: ReplyElement + picElement?: PicElement + pttElement?: PttElement + videoElement?: VideoElement + grayTipElement?: GrayTipElement + arkElement?: ArkElement + fileElement?: FileElement + liveGiftElement?: null + markdownElement?: MarkdownElement + structLongMsgElement?: any + multiForwardMsgElement?: MultiForwardMsgElement + giphyElement?: any + walletElement?: null + inlineKeyboardElement?: InlineKeyboardElement + textGiftElement?: null //???? + calendarElement?: any + yoloGameResultElement?: any + avRecordElement?: any + structMsgElement?: null + faceBubbleElement?: any + shareLocationElement?: any + tofuRecordElement?: any + taskTopMsgElement?: any + recommendedMsgElement?: any + actionBarElement?: any } \ No newline at end of file diff --git a/src/ntqqapi/wrapper.ts b/src/ntqqapi/wrapper.ts index 91567bf..40bfc8f 100644 --- a/src/ntqqapi/wrapper.ts +++ b/src/ntqqapi/wrapper.ts @@ -2,7 +2,10 @@ import { NodeIKernelBuddyService, NodeIKernelGroupService, NodeIKernelProfileService, - NodeIKernelProfileLikeService + NodeIKernelProfileLikeService, + NodeIKernelMSFService, + NodeIKernelMsgService, + NodeIKernelUixConvertService } from './services' import os from 'node:os' const Process = require('node:process') @@ -13,6 +16,9 @@ export interface NodeIQQNTWrapperSession { getGroupService(): NodeIKernelGroupService getProfileService(): NodeIKernelProfileService getProfileLikeService(): NodeIKernelProfileLikeService + getMsgService(): NodeIKernelMsgService + getMSFService(): NodeIKernelMSFService + getUixConvertService(): NodeIKernelUixConvertService } export interface WrapperApi { diff --git a/src/onebot11/action/msg/SendMsg.ts b/src/onebot11/action/msg/SendMsg.ts index 7df510c..45ce161 100644 --- a/src/onebot11/action/msg/SendMsg.ts +++ b/src/onebot11/action/msg/SendMsg.ts @@ -39,6 +39,12 @@ export interface ReturnDataType { message_id: number } +export enum ContextMode { + Normal = 0, + Private = 1, + Group = 2 +} + export function convertMessage2List(message: OB11MessageMixType, autoEscape = false) { if (typeof message === 'string') { if (autoEscape === true) { @@ -63,7 +69,7 @@ export function convertMessage2List(message: OB11MessageMixType, autoEscape = fa export async function createSendElements( messageData: OB11MessageData[], - target: Group | Friend | undefined, + peer: Peer, ignoreTypes: OB11MessageDataType[] = [], ) { let sendElements: SendMessageElement[] = [] @@ -81,7 +87,7 @@ export async function createSendElements( } break case OB11MessageDataType.at: { - if (!target) { + if (!peer) { continue } let atQQ = sendMsg.data?.qq @@ -89,7 +95,7 @@ export async function createSendElements( atQQ = atQQ.toString() if (atQQ === 'all') { // todo:查询剩余的at全体次数 - const groupCode = (target as Group)?.groupCode + const groupCode = peer.peerUid let remainAtAllCount = 1 let isAdmin: boolean = true if (groupCode) { @@ -97,7 +103,7 @@ export async function createSendElements( remainAtAllCount = (await NTQQGroupApi.getGroupAtAllRemainCount(groupCode)).atInfo .RemainAtAllCountForUin log(`群${groupCode}剩余at全体次数`, remainAtAllCount) - const self = await getGroupMember((target as Group)?.groupCode, selfInfo.uin) + const self = await getGroupMember(groupCode, selfInfo.uin) isAdmin = self?.role === GroupMemberRole.admin || self?.role === GroupMemberRole.owner } catch (e) { } @@ -108,7 +114,7 @@ export async function createSendElements( } else { // const atMember = group?.members.find(m => m.uin == atQQ) - const atMember = await getGroupMember((target as Group)?.groupCode, atQQ) + const atMember = await getGroupMember(peer.peerUid, atQQ) if (atMember) { sendElements.push( SendMsgElementConstructor.at(atQQ, atMember.uid, AtType.atUser, atMember.cardName || atMember.nick), @@ -282,6 +288,31 @@ export async function sendMsg( return returnMsg } +async function createContext(payload: OB11PostSendMsg, contextMode: ContextMode): Promise { + // This function determines the type of message by the existence of user_id / group_id, + // not message_type. + // This redundant design of Ob11 here should be blamed. + + if ((contextMode === ContextMode.Group || contextMode === ContextMode.Normal) && payload.group_id) { + const group = (await getGroup(payload.group_id))! // checked before + return { + chatType: ChatType.group, + peerUid: group.groupCode + } + } + if ((contextMode === ContextMode.Private || contextMode === ContextMode.Normal) && payload.user_id) { + const Uid = await NTQQUserApi.getUidByUin(payload.user_id.toString()) + const isBuddy = await NTQQFriendApi.isBuddy(Uid!) + //console.log("[调试代码] UIN:", payload.user_id, " UID:", Uid, " IsBuddy:", isBuddy) + return { + chatType: isBuddy ? ChatType.friend : ChatType.temp, + peerUid: Uid!, + guildId: payload.group_id || ''//临时主动发起时需要传入群号 + } + } + throw '请指定 group_id 或 user_id' +} + export class SendMsg extends BaseAction { actionName = ActionName.SendMsg @@ -321,56 +352,14 @@ export class SendMsg extends BaseAction { } protected async _handle(payload: OB11PostSendMsg) { - const peer: Peer = { - chatType: ChatType.friend, - peerUid: '', - } - let isTempMsg = false - let group: Group | undefined = undefined - let friend: Friend | undefined = undefined - const genGroupPeer = async () => { - group = await getGroup(payload.group_id?.toString()!) - peer.chatType = ChatType.group - // peer.name = group.name - peer.peerUid = group?.groupCode! - } - - const genFriendPeer = () => { - friend = friends.find((f) => f.uin == payload.user_id.toString()) - if (friend) { - // peer.name = friend.nickName - peer.peerUid = friend.uid - } - else { - peer.chatType = ChatType.temp - const tempUserUid = getUidByUin(payload.user_id.toString()) - if (!tempUserUid) { - throw `找不到私聊对象${payload.user_id}` - } - // peer.name = tempUser.nickName - isTempMsg = true - peer.peerUid = tempUserUid - } - } - if (payload?.group_id && payload.message_type === 'group') { - await genGroupPeer() - } - else if (payload?.user_id) { - genFriendPeer() - } - else if (payload.group_id) { - await genGroupPeer() - } - else { - throw '发送消息参数错误, 请指定group_id或user_id' - } + const peer = await createContext(payload, ContextMode.Normal) const messages = convertMessage2List( payload.message, payload.auto_escape === true || payload.auto_escape === 'true', ) if (this.getSpecialMsgNum(messages, OB11MessageDataType.node)) { try { - const returnMsg = await this.handleForwardNode(peer, messages as OB11MessageNode[], group) + const returnMsg = await this.handleForwardNode(peer, messages as OB11MessageNode[]) return { message_id: returnMsg?.msgShortId! } } catch (e: any) { throw '发送转发消息失败 ' + e.toString() @@ -427,7 +416,7 @@ export class SendMsg extends BaseAction { } } // log("send msg:", peer, sendElements) - const { sendElements, deleteAfterSentFiles } = await createSendElements(messages, group || friend) + const { sendElements, deleteAfterSentFiles } = await createSendElements(messages, peer) if (sendElements.length === 1) { if (sendElements[0] === null) { return { message_id: 0 } @@ -476,7 +465,7 @@ export class SendMsg extends BaseAction { } // 返回一个合并转发的消息id - private async handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[], group: Group | undefined) { + private async handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[]) { const selfPeer = { chatType: ChatType.friend, peerUid: selfInfo.uid, @@ -509,7 +498,7 @@ export class SendMsg extends BaseAction { try { const { sendElements, deleteAfterSentFiles } = await createSendElements( convertMessage2List(messageNode.data.content), - group, + destPeer ) log('开始生成转发节点', sendElements) let sendElementsSplit: SendMessageElement[][] = [] @@ -597,42 +586,6 @@ export class SendMsg extends BaseAction { return null } } - - // private genMusicElement(url: string, audio: string, title: string, content: string, image: string): SendArkElement { - // const musicJson = { - // app: 'com.tencent.structmsg', - // config: { - // ctime: 1709689928, - // forward: 1, - // token: '5c1e4905f926dd3a64a4bd3841460351', - // type: 'normal', - // }, - // extra: { app_type: 1, appid: 100497308, uin: selfInfo.uin }, - // meta: { - // news: { - // action: '', - // android_pkg_name: '', - // app_type: 1, - // appid: 100497308, - // ctime: 1709689928, - // desc: content || title, - // jumpUrl: url, - // musicUrl: audio, - // preview: image, - // source_icon: 'https://p.qpic.cn/qqconnect/0/app_100497308_1626060999/100?max-age=2592000&t=0', - // source_url: '', - // tag: 'QQ音乐', - // title: title, - // uin: selfInfo.uin, - // }, - // }, - // prompt: content || title, - // ver: '0.0.0.1', - // view: 'news', - // } - - // return SendMsgElementConstructor.ark(musicJson) - // } } export default SendMsg