import { ModifyProfileParams, User, UserDetailSource } from '@/napcat-core/types'; import { RequestUtil } from 'napcat-common/src/request'; import { InstanceContext, NapCatCore, ProfileBizType } from '..'; import { solveAsyncProblem } from 'napcat-common/src/helper'; import { Fallback, FallbackUtil } from 'napcat-common/src/fall-back'; export class NTQQUserApi { context: InstanceContext; core: NapCatCore; constructor (context: InstanceContext, core: NapCatCore) { this.context = context; this.core = core; } async getCoreAndBaseInfo (uids: string[]) { return await this.core.eventWrapper.callNoListenerEvent( 'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids ); } // 默认获取自己的 type = 2 获取别人 type = 1 async getProfileLike (uid: string, start: number, count: number, type: number = 2) { return this.context.session.getProfileLikeService().getBuddyProfileLike({ friendUids: [uid], basic: 1, vote: 1, favorite: 0, userProfile: 1, type, start, limit: count, }); } async setLongNick (longNick: string) { return this.context.session.getProfileService().setLongNick(longNick); } async setSelfOnlineStatus (status: number, extStatus: number, batteryStatus: number) { return this.context.session.getMsgService().setStatus({ status, extStatus, batteryStatus, }); } async setDiySelfOnlineStatus (faceId: string, wording: string, faceType: string) { return this.context.session.getMsgService().setStatus({ status: 10, extStatus: 2000, customStatus: { faceId, wording, faceType }, batteryStatus: 0, }); } async getBuddyRecommendContactArkJson (uin: string, sencenID = '') { return this.context.session.getBuddyService().getBuddyRecommendContactArkJson(uin, sencenID); } async like (uid: string, count = 1): Promise<{ result: number, errMsg: string, succCounts: number; }> { return this.context.session.getProfileLikeService().setBuddyProfileLike({ friendUid: uid, sourceId: 71, doLikeCount: count, doLikeTollCount: 0, }); } async setQQAvatar (filePath: string) { const ret = await this.context.session.getProfileService().setHeader(filePath); return { result: ret?.result, errMsg: ret?.errMsg }; } async setGroupAvatar (gc: string, filePath: string) { return this.context.session.getGroupService().setHeader(gc, filePath); } async fetchUserDetailInfo (uid: string, mode: UserDetailSource = UserDetailSource.KDB) { const [, profile] = await this.core.eventWrapper.callNormalEventV2( 'NodeIKernelProfileService/fetchUserDetailInfo', 'NodeIKernelProfileListener/onUserDetailInfoChanged', [ 'BuddyProfileStore', [uid], mode, [ProfileBizType.KALL], ], () => true, (profile) => profile.uid === uid ); return profile; } async getUserDetailInfo (uid: string, no_cache: boolean = false): Promise { let profile = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, no_cache ? UserDetailSource.KSERVER : UserDetailSource.KDB), uid); if (profile && profile.uin !== '0' && profile.commonExt) { return { ...profile.simpleInfo.status, ...profile.simpleInfo.vasInfo, ...profile.commonExt, ...profile.simpleInfo.baseInfo, ...profile.simpleInfo.coreInfo, qqLevel: profile.commonExt?.qqLevel, age: profile.simpleInfo.baseInfo.age, pendantId: '', nick: profile.simpleInfo.coreInfo.nick || '', }; } this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.'); profile = await this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER); if (profile && profile.uin === '0') { profile.uin = await this.core.apis.UserApi.getUidByUinV2(uid) ?? '0'; } return { ...profile.simpleInfo.status, ...profile.simpleInfo.vasInfo, ...profile.commonExt, ...profile.simpleInfo.baseInfo, ...profile.simpleInfo.coreInfo, qqLevel: profile.commonExt?.qqLevel, age: profile.simpleInfo.baseInfo.age, pendantId: '', nick: profile.simpleInfo.coreInfo.nick || '', }; } async modifySelfProfile (param: ModifyProfileParams) { return this.context.session.getProfileService().modifyDesktopMiniProfile(param); } async getCookies (domain: string) { const ClientKeyData = await this.forceFetchClientKey(); const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27'; const data = await RequestUtil.HttpsGetCookies(requestUrl); if (!data['p_skey'] || data['p_skey'].length === 0) { try { const pskey = (await this.getPSkey([domain])).domainPskeyMap.get(domain); if (pskey) data['p_skey'] = pskey; } catch { return data; } } return data; } async getPSkey (domainList: string[]) { return await this.context.session.getTipOffService().getPskey(domainList, true); } async getRobotUinRange (): Promise> { const robotUinRanges = await this.context.session.getRobotService().getRobotUinRange({ justFetchMsgConfig: '1', type: 1, version: 0, aioKeywordVersion: 0, }); return robotUinRanges?.response?.robotUinRanges; } // 需要异常处理 async getQzoneCookies () { const ClientKeyData = await this.forceFetchClientKey(); const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2Fuser.qzone.qq.com%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27'; return await RequestUtil.HttpsGetCookies(requestUrl); } // 需要异常处理 async getSKey (): Promise { const ClientKeyData = await this.forceFetchClientKey(); if (ClientKeyData.result !== 0) { throw new Error('getClientKey Error'); } const clientKey = ClientKeyData.clientKey; // const keyIndex = ClientKeyData.keyIndex; const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + clientKey + '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=19%27'; const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl); const skey = cookies['skey']; if (!skey) { throw new Error('SKey is Empty'); } return skey; } async getUidByUinV2 (uin: string) { if (!uin) { return ''; } const fallback = new Fallback((uid) => FallbackUtil.boolchecker(uid, uid !== undefined && uid.indexOf('*') === -1 && uid !== '')) .add(() => this.context.session.getUixConvertService().getUid([uin]).then((data) => data.uidInfo.get(uin))) .add(() => this.context.session.getProfileService().getUidByUin('FriendsServiceImpl', [uin]).get(uin)) .add(() => this.context.session.getGroupService().getUidByUins([uin]).then((data) => data.uids.get(uin))) .add(() => this.getUserDetailInfoByUin(uin).then((data) => data.detail.uid)); const uid = await fallback.run().catch(() => ''); return uid ?? ''; } async getUinByUidV2 (uid: string) { if (!uid) { return '0'; } const fallback = new Fallback((uin) => FallbackUtil.boolchecker(uin, uin !== undefined && uin !== '0' && uin !== '')) .add(() => this.context.session.getUixConvertService().getUin([uid]).then((data) => data.uinInfo.get(uid))) .add(() => this.context.session.getProfileService().getUinByUid('FriendsServiceImpl', [uid]).get(uid)) .add(() => this.context.session.getGroupService().getUinByUids([uid]).then((data) => data.uins.get(uid))) .add(() => this.getUserDetailInfo(uid).then((data) => data.uin)); const uin = await fallback.run().catch(() => '0'); return uin ?? '0'; } async getRecentContactListSnapShot (count: number) { return await this.context.session.getRecentContactService().getRecentContactListSnapShot(count); } async getRecentContactListSyncLimit (count: number) { return await this.context.session.getRecentContactService().getRecentContactListSyncLimit(count); } async getRecentContactListSync () { return await this.context.session.getRecentContactService().getRecentContactListSync(); } async getRecentContactList () { return await this.context.session.getRecentContactService().getRecentContactList(); } async getUserDetailInfoByUin (Uin: string) { return await this.core.eventWrapper.callNoListenerEvent( 'NodeIKernelProfileService/getUserDetailInfoByUin', Uin ); } async forceFetchClientKey () { return await this.context.session.getTicketService().forceFetchClientKey(''); } }