mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
refactor: class NTQQApi
This commit is contained in:
217
src/ntqqapi/api/file.ts
Normal file
217
src/ntqqapi/api/file.ts
Normal file
@@ -0,0 +1,217 @@
|
||||
import {callNTQQApi, GeneralCallResult, NTQQApiClass, NTQQApiMethod} from "../ntcall";
|
||||
import {
|
||||
CacheFileList,
|
||||
CacheFileListItem,
|
||||
CacheFileType,
|
||||
CacheScanResult,
|
||||
ChatCacheList, ChatCacheListItemBasic,
|
||||
ChatType,
|
||||
ElementType
|
||||
} from "../types";
|
||||
import path from "path";
|
||||
import {log} from "../../common/utils";
|
||||
import fs from "fs";
|
||||
import {ReceiveCmdS} from "../hook";
|
||||
|
||||
export class NTQQFileApi{
|
||||
static async getFileType(filePath: string) {
|
||||
return await callNTQQApi<{ ext: string }>({
|
||||
className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.FILE_TYPE, args: [filePath]
|
||||
})
|
||||
}
|
||||
static async getFileMd5(filePath: string) {
|
||||
return await callNTQQApi<string>({
|
||||
className: NTQQApiClass.FS_API,
|
||||
methodName: NTQQApiMethod.FILE_MD5,
|
||||
args: [filePath]
|
||||
})
|
||||
}
|
||||
static async copyFile(filePath: string, destPath: string) {
|
||||
return await callNTQQApi<string>({
|
||||
className: NTQQApiClass.FS_API,
|
||||
methodName: NTQQApiMethod.FILE_COPY,
|
||||
args: [{
|
||||
fromPath: filePath,
|
||||
toPath: destPath
|
||||
}]
|
||||
})
|
||||
}
|
||||
static async getFileSize(filePath: string) {
|
||||
return await callNTQQApi<number>({
|
||||
className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.FILE_SIZE, args: [filePath]
|
||||
})
|
||||
}
|
||||
// 上传文件到QQ的文件夹
|
||||
static async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC) {
|
||||
const md5 = await NTQQFileApi.getFileMd5(filePath);
|
||||
let ext = (await NTQQFileApi.getFileType(filePath))?.ext
|
||||
if (ext) {
|
||||
ext = "." + ext
|
||||
} else {
|
||||
ext = ""
|
||||
}
|
||||
let fileName = `${path.basename(filePath)}`;
|
||||
if (fileName.indexOf(".") === -1) {
|
||||
fileName += ext;
|
||||
}
|
||||
const mediaPath = await callNTQQApi<string>({
|
||||
methodName: NTQQApiMethod.MEDIA_FILE_PATH,
|
||||
args: [{
|
||||
path_info: {
|
||||
md5HexStr: md5,
|
||||
fileName: fileName,
|
||||
elementType: elementType,
|
||||
elementSubType: 0,
|
||||
thumbSize: 0,
|
||||
needCreate: true,
|
||||
downloadType: 1,
|
||||
file_uuid: ""
|
||||
}
|
||||
}]
|
||||
})
|
||||
log("media path", mediaPath)
|
||||
await NTQQFileApi.copyFile(filePath, mediaPath);
|
||||
const fileSize = await NTQQFileApi.getFileSize(filePath);
|
||||
return {
|
||||
md5,
|
||||
fileName,
|
||||
path: mediaPath,
|
||||
fileSize
|
||||
}
|
||||
}
|
||||
static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string) {
|
||||
// 用于下载收到的消息中的图片等
|
||||
if (fs.existsSync(sourcePath)) {
|
||||
return sourcePath
|
||||
}
|
||||
const apiParams = [
|
||||
{
|
||||
getReq: {
|
||||
msgId: msgId,
|
||||
chatType: chatType,
|
||||
peerUid: peerUid,
|
||||
elementId: elementId,
|
||||
thumbSize: 0,
|
||||
downloadType: 1,
|
||||
filePath: thumbPath,
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
// log("需要下载media", sourcePath);
|
||||
await callNTQQApi({
|
||||
methodName: NTQQApiMethod.DOWNLOAD_MEDIA,
|
||||
args: apiParams,
|
||||
cbCmd: ReceiveCmdS.MEDIA_DOWNLOAD_COMPLETE,
|
||||
cmdCB: (payload: { notifyInfo: { filePath: string } }) => {
|
||||
// log("media 下载完成判断", payload.notifyInfo.filePath, sourcePath);
|
||||
return payload.notifyInfo.filePath == sourcePath;
|
||||
}
|
||||
})
|
||||
return sourcePath
|
||||
}
|
||||
static async getImageSize(filePath: string) {
|
||||
return await callNTQQApi<{ width: number, height: number }>({
|
||||
className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.IMAGE_SIZE, args: [filePath]
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class NTQQFileCacheApi{
|
||||
static async setCacheSilentScan(isSilent: boolean = true) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.CACHE_SET_SILENCE,
|
||||
args: [{
|
||||
isSilent
|
||||
}, null]
|
||||
});
|
||||
}
|
||||
static getCacheSessionPathList() {
|
||||
return callNTQQApi<{
|
||||
key: string,
|
||||
value: string
|
||||
}[]>({
|
||||
className: NTQQApiClass.OS_API,
|
||||
methodName: NTQQApiMethod.CACHE_PATH_SESSION,
|
||||
});
|
||||
}
|
||||
static clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
|
||||
return callNTQQApi<any>({ // TODO: 目前还不知道真正的返回值是什么
|
||||
methodName: NTQQApiMethod.CACHE_CLEAR,
|
||||
args: [{
|
||||
keys: cacheKeys
|
||||
}, null]
|
||||
});
|
||||
}
|
||||
static addCacheScannedPaths(pathMap: object = {}) {
|
||||
return callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.CACHE_ADD_SCANNED_PATH,
|
||||
args: [{
|
||||
pathMap: {...pathMap},
|
||||
}, null]
|
||||
});
|
||||
}
|
||||
static scanCache() {
|
||||
callNTQQApi<GeneralCallResult>({
|
||||
methodName: ReceiveCmdS.CACHE_SCAN_FINISH,
|
||||
classNameIsRegister: true,
|
||||
}).then();
|
||||
return callNTQQApi<CacheScanResult>({
|
||||
methodName: NTQQApiMethod.CACHE_SCAN,
|
||||
args: [null, null],
|
||||
timeoutSecond: 300,
|
||||
});
|
||||
}
|
||||
static getHotUpdateCachePath() {
|
||||
return callNTQQApi<string>({
|
||||
className: NTQQApiClass.HOTUPDATE_API,
|
||||
methodName: NTQQApiMethod.CACHE_PATH_HOT_UPDATE
|
||||
});
|
||||
}
|
||||
|
||||
static getDesktopTmpPath() {
|
||||
return callNTQQApi<string>({
|
||||
className: NTQQApiClass.BUSINESS_API,
|
||||
methodName: NTQQApiMethod.CACHE_PATH_DESKTOP_TEMP
|
||||
});
|
||||
}
|
||||
static getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
|
||||
return new Promise<ChatCacheList>((res, rej) => {
|
||||
callNTQQApi<ChatCacheList>({
|
||||
methodName: NTQQApiMethod.CACHE_CHAT_GET,
|
||||
args: [{
|
||||
chatType: type,
|
||||
pageSize,
|
||||
order: 1,
|
||||
pageIndex
|
||||
}, null]
|
||||
}).then(list => res(list))
|
||||
.catch(e => rej(e));
|
||||
});
|
||||
}
|
||||
static getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
|
||||
const _lastRecord = lastRecord ? lastRecord : {fileType: fileType};
|
||||
|
||||
return callNTQQApi<CacheFileList>({
|
||||
methodName: NTQQApiMethod.CACHE_FILE_GET,
|
||||
args: [{
|
||||
fileType: fileType,
|
||||
restart: true,
|
||||
pageSize: pageSize,
|
||||
order: 1,
|
||||
lastRecord: _lastRecord,
|
||||
}, null]
|
||||
})
|
||||
}
|
||||
static async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.CACHE_CHAT_CLEAR,
|
||||
args: [{
|
||||
chats,
|
||||
fileKeys
|
||||
}, null]
|
||||
});
|
||||
}
|
||||
|
||||
}
|
61
src/ntqqapi/api/friend.ts
Normal file
61
src/ntqqapi/api/friend.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import {Friend, FriendRequest} from "../types";
|
||||
import {ReceiveCmdS} from "../hook";
|
||||
import {callNTQQApi, GeneralCallResult, NTQQApiMethod} from "../ntcall";
|
||||
import {friendRequests} from "../../common/data";
|
||||
|
||||
export class NTQQFriendApi{
|
||||
static async getFriends(forced = false) {
|
||||
const data = await callNTQQApi<{
|
||||
data: {
|
||||
categoryId: number,
|
||||
categroyName: string,
|
||||
categroyMbCount: number,
|
||||
buddyList: Friend[]
|
||||
}[]
|
||||
}>(
|
||||
{
|
||||
methodName: NTQQApiMethod.FRIENDS,
|
||||
args: [{force_update: forced}, undefined],
|
||||
cbCmd: ReceiveCmdS.FRIENDS
|
||||
})
|
||||
let _friends: Friend[] = [];
|
||||
for (const fData of data.data) {
|
||||
_friends.push(...fData.buddyList)
|
||||
}
|
||||
return _friends
|
||||
}
|
||||
static async likeFriend(uid: string, count = 1) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.LIKE_FRIEND,
|
||||
args: [{
|
||||
doLikeUserInfo: {
|
||||
friendUid: uid,
|
||||
sourceId: 71,
|
||||
doLikeCount: count,
|
||||
doLikeTollCount: 0
|
||||
}
|
||||
}, null]
|
||||
})
|
||||
}
|
||||
static async handleFriendRequest(sourceId: number, accept: boolean,) {
|
||||
const request: FriendRequest = friendRequests[sourceId]
|
||||
if (!request) {
|
||||
throw `sourceId ${sourceId}, 对应的好友请求不存在`
|
||||
}
|
||||
const result = await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.HANDLE_FRIEND_REQUEST,
|
||||
args: [
|
||||
{
|
||||
"approvalInfo": {
|
||||
"friendUid": request.friendUid,
|
||||
"reqTime": request.reqTime,
|
||||
accept
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
delete friendRequests[sourceId];
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
223
src/ntqqapi/api/group.ts
Normal file
223
src/ntqqapi/api/group.ts
Normal file
@@ -0,0 +1,223 @@
|
||||
import {ReceiveCmdS} from "../hook";
|
||||
import {Group, GroupMember, GroupMemberRole, GroupNotifies, GroupNotify, GroupRequestOperateTypes} from "../types";
|
||||
import {callNTQQApi, GeneralCallResult, NTQQApiClass, NTQQApiMethod} from "../ntcall";
|
||||
import {uidMaps} from "../../common/data";
|
||||
import {log} from "../../common/utils";
|
||||
import {BrowserWindow} from "electron";
|
||||
import {dbUtil} from "../../common/db";
|
||||
|
||||
export class NTQQGroupApi{
|
||||
static async getGroups(forced = false) {
|
||||
let cbCmd = ReceiveCmdS.GROUPS
|
||||
if (process.platform != "win32") {
|
||||
cbCmd = ReceiveCmdS.GROUPS_UNIX
|
||||
}
|
||||
const result = await callNTQQApi<{
|
||||
updateType: number,
|
||||
groupList: Group[]
|
||||
}>({methodName: NTQQApiMethod.GROUPS, args: [{force_update: forced}, undefined], cbCmd})
|
||||
return result.groupList
|
||||
}
|
||||
static async getGroupMembers(groupQQ: string, num = 3000): Promise<GroupMember[]> {
|
||||
const sceneId = await callNTQQApi({
|
||||
methodName: NTQQApiMethod.GROUP_MEMBER_SCENE,
|
||||
args: [{
|
||||
groupCode: groupQQ,
|
||||
scene: "groupMemberList_MainWindow"
|
||||
}]
|
||||
})
|
||||
// log("get group member sceneId", sceneId);
|
||||
try {
|
||||
const result = await callNTQQApi<{
|
||||
result: { infos: any }
|
||||
}>({
|
||||
methodName: NTQQApiMethod.GROUP_MEMBERS,
|
||||
args: [{
|
||||
sceneId: sceneId,
|
||||
num: num
|
||||
},
|
||||
null
|
||||
]
|
||||
})
|
||||
// log("members info", typeof result.result.infos, Object.keys(result.result.infos))
|
||||
const values = result.result.infos.values()
|
||||
|
||||
const members: GroupMember[] = Array.from(values)
|
||||
for (const member of members) {
|
||||
uidMaps[member.uid] = member.uin;
|
||||
}
|
||||
// log(uidMaps);
|
||||
// log("members info", values);
|
||||
log(`get group ${groupQQ} members success`)
|
||||
return members
|
||||
} catch (e) {
|
||||
log(`get group ${groupQQ} members failed`, e)
|
||||
return []
|
||||
}
|
||||
}
|
||||
static async getGroupNotifies() {
|
||||
// 获取管理员变更
|
||||
// 加群通知,退出通知,需要管理员权限
|
||||
callNTQQApi<GeneralCallResult>({
|
||||
methodName: ReceiveCmdS.GROUP_NOTIFY,
|
||||
classNameIsRegister: true,
|
||||
}).then()
|
||||
return await callNTQQApi<GroupNotifies>({
|
||||
methodName: NTQQApiMethod.GET_GROUP_NOTICE,
|
||||
cbCmd: ReceiveCmdS.GROUP_NOTIFY,
|
||||
afterFirstCmd: false,
|
||||
args: [
|
||||
{"doubt": false, "startSeq": "", "number": 14},
|
||||
null
|
||||
]
|
||||
});
|
||||
}
|
||||
static async getGroupIgnoreNotifies() {
|
||||
await NTQQGroupApi.getGroupNotifies();
|
||||
const result = callNTQQApi<GroupNotifies>({
|
||||
className: NTQQApiClass.WINDOW_API,
|
||||
methodName: NTQQApiMethod.OPEN_EXTRA_WINDOW,
|
||||
cbCmd: ReceiveCmdS.GROUP_NOTIFY,
|
||||
afterFirstCmd: false,
|
||||
args: [
|
||||
"GroupNotifyFilterWindow"
|
||||
]
|
||||
})
|
||||
// 关闭窗口
|
||||
setTimeout(() => {
|
||||
for (const w of BrowserWindow.getAllWindows()) {
|
||||
// log("close window", w.webContents.getURL())
|
||||
if (w.webContents.getURL().indexOf("#/notify-filter/") != -1) {
|
||||
w.close();
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
return result;
|
||||
}
|
||||
static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) {
|
||||
const notify: GroupNotify = await dbUtil.getGroupNotify(seq)
|
||||
if (!notify) {
|
||||
throw `${seq}对应的加群通知不存在`
|
||||
}
|
||||
// delete groupNotifies[seq];
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.HANDLE_GROUP_REQUEST,
|
||||
args: [
|
||||
{
|
||||
"doubt": false,
|
||||
"operateMsg": {
|
||||
"operateType": operateType, // 2 拒绝
|
||||
"targetMsg": {
|
||||
"seq": seq, // 通知序列号
|
||||
"type": notify.type,
|
||||
"groupCode": notify.group.groupCode,
|
||||
"postscript": reason
|
||||
}
|
||||
}
|
||||
},
|
||||
null
|
||||
]
|
||||
});
|
||||
}
|
||||
static async quitGroup(groupQQ: string) {
|
||||
await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.QUIT_GROUP,
|
||||
args: [
|
||||
{"groupCode": groupQQ},
|
||||
null
|
||||
]
|
||||
})
|
||||
}
|
||||
static async kickMember(groupQQ: string, kickUids: string[], refuseForever: boolean = false, kickReason: string = '') {
|
||||
return await callNTQQApi<GeneralCallResult>(
|
||||
{
|
||||
methodName: NTQQApiMethod.KICK_MEMBER,
|
||||
args: [
|
||||
{
|
||||
groupCode: groupQQ,
|
||||
kickUids,
|
||||
refuseForever,
|
||||
kickReason,
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
static async banMember(groupQQ: string, memList: Array<{ uid: string, timeStamp: number }>) {
|
||||
// timeStamp为秒数, 0为解除禁言
|
||||
return await callNTQQApi<GeneralCallResult>(
|
||||
{
|
||||
methodName: NTQQApiMethod.MUTE_MEMBER,
|
||||
args: [
|
||||
{
|
||||
groupCode: groupQQ,
|
||||
memList,
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
static async banGroup(groupQQ: string, shutUp: boolean) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.MUTE_GROUP,
|
||||
args: [
|
||||
{
|
||||
groupCode: groupQQ,
|
||||
shutUp
|
||||
}, null
|
||||
]
|
||||
})
|
||||
}
|
||||
static async setMemberCard(groupQQ: string, memberUid: string, cardName: string) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.SET_MEMBER_CARD,
|
||||
args: [
|
||||
{
|
||||
groupCode: groupQQ,
|
||||
uid: memberUid,
|
||||
cardName
|
||||
}, null
|
||||
]
|
||||
})
|
||||
}
|
||||
static async setMemberRole(groupQQ: string, memberUid: string, role: GroupMemberRole) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.SET_MEMBER_ROLE,
|
||||
args: [
|
||||
{
|
||||
groupCode: groupQQ,
|
||||
uid: memberUid,
|
||||
role
|
||||
}, null
|
||||
]
|
||||
})
|
||||
}
|
||||
static async setGroupName(groupQQ: string, groupName: string) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.SET_GROUP_NAME,
|
||||
args: [
|
||||
{
|
||||
groupCode: groupQQ,
|
||||
groupName
|
||||
}, null
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
// 头衔不可用
|
||||
static async setGroupTitle(groupQQ: string, uid: string, title: string) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.SET_GROUP_TITLE,
|
||||
args: [
|
||||
{
|
||||
groupCode: groupQQ,
|
||||
uid,
|
||||
title
|
||||
}, null
|
||||
]
|
||||
})
|
||||
}
|
||||
static publishGroupBulletin(groupQQ: string, title: string, content: string) {
|
||||
|
||||
}
|
||||
}
|
163
src/ntqqapi/api/msg.ts
Normal file
163
src/ntqqapi/api/msg.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
import {callNTQQApi, GeneralCallResult, NTQQApiMethod} from "../ntcall";
|
||||
import {ChatType, RawMessage, SendMessageElement} from "../types";
|
||||
import {log, sleep} from "../../common/utils";
|
||||
import {dbUtil} from "../../common/db";
|
||||
import {selfInfo} from "../../common/data";
|
||||
import {ReceiveCmdS, registerReceiveHook} from "../hook";
|
||||
export let sendMessagePool: Record<string, ((sendSuccessMsg: RawMessage) => void) | null> = {}// peerUid: callbackFunnc
|
||||
|
||||
export interface Peer {
|
||||
chatType: ChatType
|
||||
peerUid: string // 如果是群聊uid为群号,私聊uid就是加密的字符串
|
||||
guildId?: ""
|
||||
}
|
||||
|
||||
export class NTQQMsgApi {
|
||||
static async activateChat(peer: Peer) {
|
||||
return await callNTQQApi({
|
||||
methodName: NTQQApiMethod.ADD_ACTIVE_CHAT,
|
||||
args: [{peer, cnt: 20}]
|
||||
})
|
||||
}
|
||||
static async recallMsg(peer: Peer, msgIds: string[]) {
|
||||
return await callNTQQApi({
|
||||
methodName: NTQQApiMethod.RECALL_MSG,
|
||||
args: [{
|
||||
peer,
|
||||
msgIds
|
||||
}, null]
|
||||
})
|
||||
}
|
||||
|
||||
static async sendMsg(peer: Peer, msgElements: SendMessageElement[],
|
||||
waitComplete = true, timeout = 10000) {
|
||||
const peerUid = peer.peerUid
|
||||
|
||||
// 等待上一个相同的peer发送完
|
||||
let checkLastSendUsingTime = 0;
|
||||
const waitLastSend = async () => {
|
||||
if (checkLastSendUsingTime > timeout) {
|
||||
throw ("发送超时")
|
||||
}
|
||||
let lastSending = sendMessagePool[peer.peerUid]
|
||||
if (lastSending) {
|
||||
// log("有正在发送的消息,等待中...")
|
||||
await sleep(500);
|
||||
checkLastSendUsingTime += 500;
|
||||
return await waitLastSend();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
await waitLastSend();
|
||||
|
||||
let sentMessage: RawMessage = null;
|
||||
sendMessagePool[peerUid] = async (rawMessage: RawMessage) => {
|
||||
delete sendMessagePool[peerUid];
|
||||
sentMessage = rawMessage;
|
||||
}
|
||||
|
||||
let checkSendCompleteUsingTime = 0;
|
||||
const checkSendComplete = async (): Promise<RawMessage> => {
|
||||
if (sentMessage) {
|
||||
if (waitComplete) {
|
||||
if ((await dbUtil.getMsgByLongId(sentMessage.msgId)).sendStatus == 2) {
|
||||
return sentMessage
|
||||
}
|
||||
} else {
|
||||
return sentMessage
|
||||
}
|
||||
// log(`给${peerUid}发送消息成功`)
|
||||
}
|
||||
checkSendCompleteUsingTime += 500
|
||||
if (checkSendCompleteUsingTime > timeout) {
|
||||
throw ('发送超时')
|
||||
}
|
||||
await sleep(500)
|
||||
return await checkSendComplete()
|
||||
}
|
||||
|
||||
callNTQQApi({
|
||||
methodName: NTQQApiMethod.SEND_MSG,
|
||||
args: [{
|
||||
msgId: "0",
|
||||
peer, msgElements,
|
||||
msgAttributeInfos: new Map(),
|
||||
}, null]
|
||||
}).then()
|
||||
return await checkSendComplete()
|
||||
}
|
||||
|
||||
static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.FORWARD_MSG,
|
||||
args: [
|
||||
{
|
||||
msgIds: msgIds,
|
||||
srcContact: srcPeer,
|
||||
dstContacts: [
|
||||
destPeer
|
||||
],
|
||||
commentElements: [],
|
||||
msgAttributeInfos: new Map()
|
||||
},
|
||||
null,
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
static async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
||||
const msgInfos = msgIds.map(id => {
|
||||
return {msgId: id, senderShowName: selfInfo.nick}
|
||||
})
|
||||
const apiArgs = [
|
||||
{
|
||||
msgInfos,
|
||||
srcContact: srcPeer,
|
||||
dstContact: destPeer,
|
||||
commentElements: [],
|
||||
msgAttributeInfos: new Map()
|
||||
},
|
||||
null,
|
||||
]
|
||||
return await new Promise<RawMessage>((resolve, reject) => {
|
||||
let complete = false
|
||||
setTimeout(() => {
|
||||
if (!complete) {
|
||||
reject("转发消息超时");
|
||||
}
|
||||
}, 5000)
|
||||
registerReceiveHook(ReceiveCmdS.SELF_SEND_MSG, async (payload: { msgRecord: RawMessage }) => {
|
||||
const msg = payload.msgRecord
|
||||
// 需要判断它是转发的消息,并且识别到是当前转发的这一条
|
||||
const arkElement = msg.elements.find(ele => ele.arkElement)
|
||||
if (!arkElement) {
|
||||
// log("收到的不是转发消息")
|
||||
return
|
||||
}
|
||||
const forwardData: any = JSON.parse(arkElement.arkElement.bytesData)
|
||||
if (forwardData.app != 'com.tencent.multimsg') {
|
||||
return
|
||||
}
|
||||
if (msg.peerUid == destPeer.peerUid && msg.senderUid == selfInfo.uid) {
|
||||
complete = true
|
||||
await dbUtil.addMsg(msg)
|
||||
resolve(msg)
|
||||
log('转发消息成功:', payload)
|
||||
}
|
||||
})
|
||||
callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.MULTI_FORWARD_MSG,
|
||||
args: apiArgs
|
||||
}).then(result => {
|
||||
log("转发消息结果:", result, apiArgs)
|
||||
if (result.result !== 0) {
|
||||
complete = true;
|
||||
reject("转发消息失败," + JSON.stringify(result));
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
57
src/ntqqapi/api/user.ts
Normal file
57
src/ntqqapi/api/user.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import {callNTQQApi, GeneralCallResult, NTQQApiClass, NTQQApiMethod} from "../ntcall";
|
||||
import {SelfInfo, User} from "../types";
|
||||
import {ReceiveCmdS} from "../hook";
|
||||
import {uidMaps} from "../../common/data";
|
||||
|
||||
|
||||
export class NTQQUserApi{
|
||||
static async setQQAvatar(filePath: string) {
|
||||
return await callNTQQApi<GeneralCallResult>({
|
||||
methodName: NTQQApiMethod.SET_QQ_AVATAR,
|
||||
args: [{
|
||||
path:filePath
|
||||
}, null],
|
||||
timeoutSecond: 10 // 10秒不一定够
|
||||
});
|
||||
}
|
||||
|
||||
static async getSelfInfo() {
|
||||
return await callNTQQApi<SelfInfo>({
|
||||
className: NTQQApiClass.GLOBAL_DATA,
|
||||
methodName: NTQQApiMethod.SELF_INFO, timeoutSecond: 2
|
||||
})
|
||||
}
|
||||
static async getUserInfo(uid: string) {
|
||||
const result = await callNTQQApi<{ profiles: Map<string, User> }>({
|
||||
methodName: NTQQApiMethod.USER_INFO,
|
||||
args: [{force: true, uids: [uid]}, undefined],
|
||||
cbCmd: ReceiveCmdS.USER_INFO
|
||||
})
|
||||
return result.profiles.get(uid)
|
||||
}
|
||||
static async getUserDetailInfo(uid: string) {
|
||||
const result = await callNTQQApi<{ info: User }>({
|
||||
methodName: NTQQApiMethod.USER_DETAIL_INFO,
|
||||
cbCmd: ReceiveCmdS.USER_DETAIL_INFO,
|
||||
afterFirstCmd: false,
|
||||
cmdCB: (payload) => {
|
||||
const success = payload.info.uid == uid
|
||||
// log("get user detail info", success, uid, payload)
|
||||
return success
|
||||
},
|
||||
args: [
|
||||
{
|
||||
uid
|
||||
},
|
||||
null
|
||||
]
|
||||
})
|
||||
const info = result.info
|
||||
if (info?.uin) {
|
||||
uidMaps[info.uid] = info.uin
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user