mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-12-18 20:30:08 +08:00
* feat: pnpm new * Refactor build and release workflows, update dependencies Switch build scripts and workflows from npm to pnpm, update build and artifact paths, and simplify release workflow by removing version detection and changelog steps. Add new dependencies (silk-wasm, express, ws, node-pty-prebuilt-multiarch), update exports in package.json files, and add vite config for napcat-framework. Also, rename manifest.json for framework package and fix static asset copying in shell build config.
249 lines
8.9 KiB
TypeScript
249 lines
8.9 KiB
TypeScript
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<User> {
|
|
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<Array<unknown>> {
|
|
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<string | undefined> {
|
|
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<string | undefined>((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<string | undefined>((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('');
|
|
}
|
|
}
|