From 72eb01337146e87b5841564b767163b766520c45 Mon Sep 17 00:00:00 2001 From: idranme Date: Mon, 5 Aug 2024 20:44:28 +0800 Subject: [PATCH] fix --- src/ntqqapi/api/file.ts | 8 ++++-- src/ntqqapi/api/friend.ts | 4 +-- src/ntqqapi/api/group.ts | 59 ++++++++++++++++++++++++++------------- src/ntqqapi/api/msg.ts | 3 +- src/ntqqapi/api/rkey.ts | 53 +++++++++++++++++++---------------- src/ntqqapi/api/user.ts | 9 +++--- src/ntqqapi/api/webapi.ts | 23 +++++++++++---- src/ntqqapi/wrapper.ts | 33 ++++++++++++---------- 8 files changed, 119 insertions(+), 73 deletions(-) diff --git a/src/ntqqapi/api/file.ts b/src/ntqqapi/api/file.ts index 0a05f22..6a539fd 100644 --- a/src/ntqqapi/api/file.ts +++ b/src/ntqqapi/api/file.ts @@ -11,8 +11,8 @@ import { IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT, PicElement, } from '../types' -import path from 'path' -import fs from 'fs' +import path from 'node:path' +import fs from 'node:fs' import { ReceiveCmdS } from '../hook' import { log } from '@/common/utils' import { rkeyManager } from '@/ntqqapi/api/rkey' @@ -21,12 +21,14 @@ import { Peer } from '@/ntqqapi/types/msg' export class NTQQFileApi { static async getVideoUrl(peer: Peer, msgId: string, elementId: string): Promise { - return (await wrapperApi.NodeIQQNTWrapperSession.getRichMediaService().getVideoPlayUrlV2(peer, + const session = wrapperApi.NodeIQQNTWrapperSession + return (await session.getRichMediaService().getVideoPlayUrlV2(peer, msgId, elementId, 0, { downSourceType: 1, triggerType: 1 })).urlResult?.domainUrl[0]?.url; } + static async getFileType(filePath: string) { return await callNTQQApi<{ ext: string }>({ className: NTQQApiClass.FS_API, diff --git a/src/ntqqapi/api/friend.ts b/src/ntqqapi/api/friend.ts index f592eb8..2e3a5ec 100644 --- a/src/ntqqapi/api/friend.ts +++ b/src/ntqqapi/api/friend.ts @@ -2,7 +2,6 @@ import { Friend, FriendRequest, FriendV2 } from '../types' import { ReceiveCmdS } from '../hook' import { callNTQQApi, GeneralCallResult, NTQQApiMethod } from '../ntcall' import { friendRequests } from '../../common/data' -import { log } from '../../common/utils' import { wrapperApi } from '@/ntqqapi/wrapper' import { BuddyListReqType, NodeIKernelProfileService } from '../services' import { NTEventDispatch } from '../../common/utils/EventTask' @@ -70,7 +69,8 @@ export class NTQQFriendApi { static async getBuddyV2(refresh = false): Promise { const uids: string[] = [] - const buddyService = wrapperApi.NodeIQQNTWrapperSession.getBuddyService() + const session = wrapperApi.NodeIQQNTWrapperSession + const buddyService = session.getBuddyService() const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) uids.push(...buddyListV2.data.flatMap(item => item.buddyUids)) const data = await NTEventDispatch.CallNoListenerEvent( diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index 1d2a26e..a2cf620 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -8,22 +8,23 @@ import { NTQQWindowApi, NTQQWindows } from './window' import { wrapperApi } from '../wrapper' export class NTQQGroupApi { - - static async activateMemberListChange(){ + static async activateMemberListChange() { return await callNTQQApi({ methodName: NTQQApiMethod.ACTIVATE_MEMBER_LIST_CHANGE, classNameIsRegister: true, args: [], }) } - static async activateMemberInfoChange(){ + + static async activateMemberInfoChange() { return await callNTQQApi({ methodName: NTQQApiMethod.ACTIVATE_MEMBER_INFO_CHANGE, classNameIsRegister: true, args: [], }) } - static async getGroupAllInfo(groupCode: string, source: number=4){ + + static async getGroupAllInfo(groupCode: string, source: number = 4) { return await callNTQQApi({ methodName: NTQQApiMethod.GET_GROUP_ALL_INFO, args: [ @@ -35,6 +36,7 @@ export class NTQQGroupApi { ], }) } + static async getGroups(forced = false) { // let cbCmd = ReceiveCmdS.GROUPS // if (process.platform != 'win32') { @@ -52,6 +54,7 @@ export class NTQQGroupApi { log('get groups result', result) return result.groupList } + static async getGroupMembers(groupQQ: string, num = 3000): Promise { const sceneId = await callNTQQApi({ methodName: NTQQApiMethod.GROUP_MEMBER_SCENE, @@ -62,7 +65,7 @@ export class NTQQGroupApi { }, ], }) - // log("get group member sceneId", sceneId); + // log("get group member sceneId", sceneId) try { const result = await callNTQQApi<{ result: { infos: any } @@ -83,8 +86,8 @@ export class NTQQGroupApi { for (const member of members) { uidMaps[member.uid] = member.uin } - // log(uidMaps); - // log("members info", values); + // log(uidMaps) + // log("members info", values) log(`get group ${groupQQ} members success`) return members } catch (e) { @@ -92,7 +95,8 @@ export class NTQQGroupApi { return [] } } - static async getGroupMembersInfo(groupCode: string, uids: string[], forceUpdate: boolean=false) { + + static async getGroupMembersInfo(groupCode: string, uids: string[], forceUpdate: boolean = false) { return await callNTQQApi({ methodName: NTQQApiMethod.GROUP_MEMBERS_INFO, args: [ @@ -105,6 +109,7 @@ export class NTQQGroupApi { ], }) } + static async getGroupNotifies() { // 获取管理员变更 // 加群通知,退出通知,需要管理员权限 @@ -119,6 +124,7 @@ export class NTQQGroupApi { args: [{ doubt: false, startSeq: '', number: 14 }, null], }) } + static async getGroupIgnoreNotifies() { await NTQQGroupApi.getGroupNotifies() return await NTQQWindowApi.openWindow( @@ -127,12 +133,13 @@ export class NTQQGroupApi { ReceiveCmdS.GROUP_NOTIFY, ) } + static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) { const notify: GroupNotify = await dbUtil.getGroupNotify(seq) if (!notify) { throw `${seq}对应的加群通知不存在` } - // delete groupNotifies[seq]; + // delete groupNotifies[seq] return await callNTQQApi({ methodName: NTQQApiMethod.HANDLE_GROUP_REQUEST, args: [ @@ -152,6 +159,7 @@ export class NTQQGroupApi { ], }) } + static async quitGroup(groupQQ: string) { const result = await callNTQQApi({ methodName: NTQQApiMethod.QUIT_GROUP, @@ -162,6 +170,7 @@ export class NTQQGroupApi { } return result } + static async kickMember( groupQQ: string, kickUids: string[], @@ -180,7 +189,8 @@ export class NTQQGroupApi { ], }) } - static async banMember(groupQQ: string, memList: Array<{ uid: string; timeStamp: number }>) { + + static async banMember(groupQQ: string, memList: Array<{ uid: string, timeStamp: number }>) { // timeStamp为秒数, 0为解除禁言 return await callNTQQApi({ methodName: NTQQApiMethod.MUTE_MEMBER, @@ -192,6 +202,7 @@ export class NTQQGroupApi { ], }) } + static async banGroup(groupQQ: string, shutUp: boolean) { return await callNTQQApi({ methodName: NTQQApiMethod.MUTE_GROUP, @@ -204,6 +215,7 @@ export class NTQQGroupApi { ], }) } + static async setMemberCard(groupQQ: string, memberUid: string, cardName: string) { NTQQGroupApi.activateMemberListChange().then().catch(log) const res = await callNTQQApi({ @@ -218,8 +230,9 @@ export class NTQQGroupApi { ], }) NTQQGroupApi.getGroupMembersInfo(groupQQ, [memberUid], true).then().catch(log) - return res; + return res } + static async setMemberRole(groupQQ: string, memberUid: string, role: GroupMemberRole) { return await callNTQQApi({ methodName: NTQQApiMethod.SET_MEMBER_ROLE, @@ -233,6 +246,7 @@ export class NTQQGroupApi { ], }) } + static async setGroupName(groupQQ: string, groupName: string) { return await callNTQQApi({ methodName: NTQQApiMethod.SET_GROUP_NAME, @@ -282,29 +296,34 @@ export class NTQQGroupApi { ], }) } - static publishGroupBulletin(groupQQ: string, title: string, content: string) {} + + static publishGroupBulletin(groupQQ: string, title: string, content: string) { } + static async removeGroupEssence(GroupCode: string, msgId: string) { + const session = wrapperApi.NodeIQQNTWrapperSession // 代码没测过 // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom - let MsgData = await wrapperApi.NodeIQQNTWrapperSession.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false); + 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) - }; - // GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数 - return wrapperApi.NodeIQQNTWrapperSession.getGroupService().removeGroupEssence(param); + } + // GetMsgByShoretID(ShoretID) -> MsgService.getMsgs(Peer,MsgId,1,false) -> 组出参数 + return session.getGroupService().removeGroupEssence(param) } + static async addGroupEssence(GroupCode: string, msgId: string) { + const session = wrapperApi.NodeIQQNTWrapperSession // 代码没测过 // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom - let MsgData = await wrapperApi.NodeIQQNTWrapperSession.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false); + 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) - }; - // GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数 - return wrapperApi.NodeIQQNTWrapperSession.getGroupService().addGroupEssence(param); + } + // 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 b5619e7..ae19a0a 100644 --- a/src/ntqqapi/api/msg.ts +++ b/src/ntqqapi/api/msg.ts @@ -289,6 +289,7 @@ export class NTQQMsgApi { }) } static async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) { - return await wrapperApi.NodeIQQNTWrapperSession.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z); + const session = wrapperApi.NodeIQQNTWrapperSession + return await session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z); } } diff --git a/src/ntqqapi/api/rkey.ts b/src/ntqqapi/api/rkey.ts index 25ebbaf..c3a59cf 100644 --- a/src/ntqqapi/api/rkey.ts +++ b/src/ntqqapi/api/rkey.ts @@ -2,58 +2,63 @@ import { log } from '@/common/utils' -interface ServerRkeyData{ - group_rkey: string; - private_rkey: string; - expired_time: number; +interface ServerRkeyData { + group_rkey: string + private_rkey: string + expired_time: number } class RkeyManager { - serverUrl: string = ''; + serverUrl: string = '' private rkeyData: ServerRkeyData = { group_rkey: '', private_rkey: '', expired_time: 0 - }; - constructor(serverUrl: string) { - this.serverUrl = serverUrl; } - async getRkey(){ + + constructor(serverUrl: string) { + this.serverUrl = serverUrl + } + + async getRkey() { if (this.isExpired()) { try { - await this.refreshRkey(); + await this.refreshRkey() } catch (e) { - log('获取rkey失败', e); + log('获取rkey失败', e) } } - return this.rkeyData; + return this.rkeyData } isExpired(): boolean { - const now = new Date().getTime() / 1000; - // console.log(`now: ${now}, expired_time: ${this.rkeyData.expired_time}`); - return now > this.rkeyData.expired_time; + const now = new Date().getTime() / 1000 + // console.log(`now: ${now}, expired_time: ${this.rkeyData.expired_time}`) + return now > this.rkeyData.expired_time } + async refreshRkey(): Promise { //刷新rkey - this.rkeyData = await this.fetchServerRkey(); + this.rkeyData = await this.fetchServerRkey() } - async fetchServerRkey(){ + + async fetchServerRkey() { return new Promise((resolve, reject) => { fetch(this.serverUrl) .then(response => { if (!response.ok) { - return reject(response.statusText); // 请求失败,返回错误信息 + return reject(response.statusText) // 请求失败,返回错误信息 } - return response.json(); // 解析 JSON 格式的响应体 + return response.json() // 解析 JSON 格式的响应体 }) .then(data => { - resolve(data); + resolve(data) }) .catch(error => { - reject(error); - }); - }); + reject(error) + }) + }) } } -export const rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey'); + +export const rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey') diff --git a/src/ntqqapi/api/user.ts b/src/ntqqapi/api/user.ts index 010d15a..e5da023 100644 --- a/src/ntqqapi/api/user.ts +++ b/src/ntqqapi/api/user.ts @@ -6,7 +6,7 @@ import { cacheFunc, isQQ998, log, sleep } from '../../common/utils' import { wrapperApi } from '@/ntqqapi/wrapper' import { RequestUtil } from '@/common/utils/request' -let userInfoCache: Record = {} // uid: User +const userInfoCache: Record = {} // uid: User export interface ClientKeyData extends GeneralCallResult { url: string; @@ -149,7 +149,8 @@ export class NTQQUserApi { } static async getPSkey(domains: string[]): Promise> { - const res = await wrapperApi.NodeIQQNTWrapperSession.getTipOffService().getPskey(domains, true) + const session = wrapperApi.NodeIQQNTWrapperSession + const res = await session.getTipOffService().getPskey(domains, true) if (res.result !== 0) { throw new Error(`获取Pskey失败: ${res.errMsg}`) } @@ -157,7 +158,7 @@ export class NTQQUserApi { } static async getClientKey(): Promise { - return await wrapperApi.NodeIQQNTWrapperSession.getTicketService().forceFetchClientKey('') + const session = wrapperApi.NodeIQQNTWrapperSession + return await session.getTicketService().forceFetchClientKey('') } - } diff --git a/src/ntqqapi/api/webapi.ts b/src/ntqqapi/api/webapi.ts index cd73440..8f840ce 100644 --- a/src/ntqqapi/api/webapi.ts +++ b/src/ntqqapi/api/webapi.ts @@ -1,7 +1,8 @@ -import { WebGroupData, groups, selfInfo } from '@/common/data'; -import { log } from '@/common/utils/log'; -import { NTQQUserApi } from './user'; -import { RequestUtil } from '@/common/utils/request'; +import { WebGroupData, groups, selfInfo } from '@/common/data' +import { log } from '@/common/utils/log' +import { NTQQUserApi } from './user' +import { RequestUtil } from '@/common/utils/request' + export enum WebHonorType { ALL = 'all', TALKACTIVE = 'talkative', @@ -10,6 +11,7 @@ export enum WebHonorType { STORONGE_NEWBI = 'strong_newbie', EMOTION = 'emotion' } + export interface WebApiGroupMember { uin: number role: number @@ -27,6 +29,7 @@ export interface WebApiGroupMember { qage: number rm: number } + interface WebApiGroupMemberRet { ec: number errcode: number @@ -41,6 +44,7 @@ interface WebApiGroupMemberRet { search_count: number extmode: number } + export interface WebApiGroupNoticeFeed { u: number//发送者 fid: string//fid @@ -69,6 +73,7 @@ export interface WebApiGroupNoticeFeed { is_read: number is_all_confirm: number } + export interface WebApiGroupNoticeRet { ec: number em: string @@ -89,6 +94,7 @@ export interface WebApiGroupNoticeRet { svrt: number ad: number } + interface GroupEssenceMsg { group_code: string msg_seq: number @@ -102,6 +108,7 @@ interface GroupEssenceMsg { msg_content: any[] can_be_removed: true } + export interface GroupEssenceMsgRet { retcode: number retmsg: string @@ -112,9 +119,10 @@ export interface GroupEssenceMsgRet { config_page_url: string } } + export class WebApi { static async getGroupEssenceMsg(GroupCode: string, page_start: string): Promise { - const {cookies: CookieValue, bkn: Bkn} = (await NTQQUserApi.getCookies('qun.qq.com')) + const { cookies: CookieValue, bkn: Bkn } = (await NTQQUserApi.getCookies('qun.qq.com')) const url = 'https://qun.qq.com/cgi-bin/group_digest/digest_list?bkn=' + Bkn + '&group_code=' + GroupCode + '&page_start=' + page_start + '&page_limit=20'; let ret; try { @@ -128,6 +136,7 @@ export class WebApi { } return ret; } + static async getGroupMembers(GroupCode: string, cached: boolean = true): Promise { log('webapi 获取群成员', GroupCode); let MemberData: Array = new Array(); @@ -190,6 +199,7 @@ export class WebApi { // const res = await this.request(url); // return await res.json(); // } + static async setGroupNotice(GroupCode: string, Content: string = '') { //https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?bkn=${bkn} //qid=${群号}&bkn=${bkn}&text=${内容}&pinned=0&type=1&settings={"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1} @@ -213,6 +223,7 @@ export class WebApi { } return undefined; } + static async getGrouptNotice(GroupCode: string): Promise { const _Pskey = (await NTQQUserApi.getPSkey(['qun.qq.com']))['qun.qq.com']; const _Skey = await NTQQUserApi.getSkey(); @@ -236,6 +247,7 @@ export class WebApi { } return undefined; } + static genBkn(sKey: string) { sKey = sKey || ''; let hash = 5381; @@ -247,6 +259,7 @@ export class WebApi { return (hash & 0x7FFFFFFF).toString(); } + //实现未缓存 考虑2h缓存 static async getGroupHonorInfo(groupCode: string, getType: WebHonorType) { async function getDataInternal(Internal_groupCode: string, Internal_type: number) { diff --git a/src/ntqqapi/wrapper.ts b/src/ntqqapi/wrapper.ts index 7ca8ef7..e17beb1 100644 --- a/src/ntqqapi/wrapper.ts +++ b/src/ntqqapi/wrapper.ts @@ -1,26 +1,31 @@ -import path from 'node:path' -import fs from 'node:fs' -import { qqPkgInfo } from '../common/utils/QQBasicInfo' import { NodeIKernelBuddyService } from './services/NodeIKernelBuddyService' +import os from 'node:os' +const Process = require('node:process') export interface NodeIQQNTWrapperSession { [key: string]: any - new(): NodeIQQNTWrapperSession getBuddyService(): NodeIKernelBuddyService } export interface WrapperNodeApi { [key: string]: any - NodeIQQNTWrapperSession: NodeIQQNTWrapperSession + NodeIQQNTWrapperSession?: NodeIQQNTWrapperSession } -let wrapperNodePath = path.resolve(path.dirname(process.execPath), './resources/app/wrapper.node') -if (!fs.existsSync(wrapperNodePath)) { - wrapperNodePath = path.join(path.dirname(process.execPath), `resources/app/versions/${qqPkgInfo.version}/wrapper.node`) -} -const nativemodule: any = { exports: {} } -process.dlopen(nativemodule, wrapperNodePath) -const wrapperApi: WrapperNodeApi = nativemodule.exports +export const wrapperApi: WrapperNodeApi = {} -export { wrapperApi } -export default wrapperApi \ No newline at end of file +Process.dlopenOrig = Process.dlopen + +Process.dlopen = function (module, filename, flags = os.constants.dlopen.RTLD_LAZY) { + const dlopenRet = this.dlopenOrig(module, filename, flags) + for (let export_name in module.exports) { + module.exports[export_name] = new Proxy(module.exports[export_name], { + construct: (target, args, _newTarget) => { + const ret = new target(...args) + if (export_name === 'NodeIQQNTWrapperSession') wrapperApi.NodeIQQNTWrapperSession = ret + return ret + }, + }) + } + return dlopenRet +} \ No newline at end of file