mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-02-06 21:10:23 +00:00
feat: core code
This commit is contained in:
67
src/core/.eslintrc.cjs
Normal file
67
src/core/.eslintrc.cjs
Normal file
@@ -0,0 +1,67 @@
|
||||
module.exports = {
|
||||
'root': true,
|
||||
'env': {
|
||||
'es2021': true,
|
||||
'node': true
|
||||
},
|
||||
'extends': [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended'
|
||||
],
|
||||
'overrides': [
|
||||
{
|
||||
'env': {
|
||||
'node': true
|
||||
},
|
||||
'files': [
|
||||
'.eslintrc.{js,cjs}'
|
||||
],
|
||||
'parserOptions': {
|
||||
'sourceType': 'script'
|
||||
}
|
||||
}
|
||||
],
|
||||
'parser': '@typescript-eslint/parser',
|
||||
'parserOptions': {
|
||||
'ecmaVersion': 'latest',
|
||||
'sourceType': 'module'
|
||||
},
|
||||
'plugins': [
|
||||
'@typescript-eslint',
|
||||
'import'
|
||||
],
|
||||
'settings': {
|
||||
'import/parsers': {
|
||||
'@typescript-eslint/parser': ['.ts']
|
||||
},
|
||||
'import/resolver': {
|
||||
'typescript': {
|
||||
'alwaysTryTypes': true
|
||||
}
|
||||
}
|
||||
},
|
||||
'rules': {
|
||||
'indent': [
|
||||
'error',
|
||||
2
|
||||
],
|
||||
'linebreak-style': [
|
||||
'error',
|
||||
'unix'
|
||||
],
|
||||
'quotes': [
|
||||
'error',
|
||||
'single'
|
||||
],
|
||||
'semi': [
|
||||
'error',
|
||||
'always'
|
||||
],
|
||||
'no-unused-vars': 'off',
|
||||
'no-async-promise-executor': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
}
|
||||
};
|
||||
5
src/core/.gitignore
vendored
Normal file
5
src/core/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.idea/
|
||||
node_modules/
|
||||
dist/
|
||||
lib/
|
||||
package-lock.json
|
||||
3
src/core/README.md
Normal file
3
src/core/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# @napneko/core
|
||||
|
||||
此仓库目前只用于隐藏源码,目前无法进行单独打包,只是作为 NapCatQQ 的 git submodule 引用。
|
||||
51
src/core/build.cjs
Normal file
51
src/core/build.cjs
Normal file
@@ -0,0 +1,51 @@
|
||||
const swc = require("@swc/core");
|
||||
const glob = require('glob');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
const files = glob.sync('src/**/*.ts');
|
||||
|
||||
function transfrom(file) {
|
||||
return swc
|
||||
.transformFile(file, {
|
||||
// Some options cannot be specified in .swcrc
|
||||
sourceMaps: false,
|
||||
// Input files are treated as module by default.
|
||||
// isModule: false,
|
||||
module: {
|
||||
type: 'commonjs'
|
||||
},
|
||||
|
||||
// All options below can be configured via .swcrc
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: "typescript",
|
||||
decorators: true,
|
||||
},
|
||||
transform: {
|
||||
"legacyDecorator": true,
|
||||
"decoratorMetadata": true
|
||||
},
|
||||
target: 'es2017'
|
||||
},
|
||||
// "keepClassNames": true,
|
||||
// "loose": true
|
||||
})
|
||||
.then((output) => {
|
||||
// console.log(output.code); // transformed code
|
||||
return {
|
||||
file,
|
||||
output
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const result = await Promise.all(files.map((file) => {
|
||||
return transfrom(file)
|
||||
}));
|
||||
|
||||
await Promise.all(result.map((item) => {
|
||||
return fs.outputFile(item.file.replace('src', 'dist').replace('.ts', '.js'), item.output.code)
|
||||
}));
|
||||
//console.timeEnd('swc build');
|
||||
})()
|
||||
45
src/core/package.json
Normal file
45
src/core/package.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "@napneko/core",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./lib/index.js",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "eslint --fix ./src/**/*.ts",
|
||||
"build": "npx tsc --target es2022 --experimentalDecorators && node ./scripts/obfuscator.cjs"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/NapNeko/core.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/NapNeko/core/issues"
|
||||
},
|
||||
"homepage": "https://github.com/NapNeko/core#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.7",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.24.7",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@swc/core": "^1.6.1",
|
||||
"@types/node": "^20.12.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-standard-with-typescript": "^43.0.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-n": "^16.6.2",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.8",
|
||||
"vite-plugin-babel": "^1.2.0",
|
||||
"vite-plugin-dts": "^3.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@log4js-node/log4js-api": "^1.0.2"
|
||||
}
|
||||
}
|
||||
22
src/core/pub-package.json
Normal file
22
src/core/pub-package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@napneko/core",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "eslint --fix ./src/**/*.ts",
|
||||
"build:dev": "vite build --mode development",
|
||||
"build:prod": "vite build --mode production",
|
||||
"build": "npm run build:dev"
|
||||
},
|
||||
"author": "NapNeko",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/NapNeko/NapCatQQ/issues"
|
||||
},
|
||||
"homepage": "https://github.com/NapNeko/NapCatQQ#readme"
|
||||
}
|
||||
45
src/core/scripts/obfuscator.cjs
Normal file
45
src/core/scripts/obfuscator.cjs
Normal file
@@ -0,0 +1,45 @@
|
||||
let fs = require('fs');
|
||||
let path = require('path');
|
||||
let JavaScriptObfuscator = require('javascript-obfuscator');
|
||||
|
||||
const dirPath = path.join(__dirname, '../dist/core');
|
||||
const outputPath = dirPath;
|
||||
|
||||
if (!fs.existsSync(outputPath)) {
|
||||
fs.mkdirSync(outputPath, {recursive: true});
|
||||
}
|
||||
|
||||
function obfuscateDir(currentPath, outputDir) {
|
||||
fs.readdir(currentPath, {withFileTypes: true}, (err, entries) => {
|
||||
if (err) throw err;
|
||||
|
||||
entries.forEach(entry => {
|
||||
const localBasePath = path.join(currentPath, entry.name);
|
||||
const outputLocalBasePath = path.join(outputDir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// 如果是目录,递归调用
|
||||
if (!fs.existsSync(outputLocalBasePath)) {
|
||||
fs.mkdirSync(outputLocalBasePath, {recursive: true});
|
||||
}
|
||||
obfuscateDir(localBasePath, outputLocalBasePath);
|
||||
} else if (entry.isFile() && path.extname(entry.name) === '.js') {
|
||||
// 如果是文件且为 .js,进行混淆
|
||||
fs.readFile(localBasePath, (err, content)=>{
|
||||
// console.log('read file', localBasePath);
|
||||
const obfuscated = JavaScriptObfuscator.obfuscate(content.toString(), {
|
||||
compact: true,
|
||||
controlFlowFlattening: true
|
||||
});
|
||||
// console.log('obfuscate file', localBasePath);
|
||||
fs.writeFile(outputLocalBasePath, obfuscated.getObfuscatedCode(), ()=>{
|
||||
// console.log(`[NapCat] [Obfuscator] ${localBasePath} => ${outputLocalBasePath}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 开始混淆
|
||||
obfuscateDir(dirPath, outputPath);
|
||||
29
src/core/src/adapters/NodeIDependsAdapter.ts
Normal file
29
src/core/src/adapters/NodeIDependsAdapter.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { log } from "@/common/utils/log";
|
||||
|
||||
interface IDependsAdapter {
|
||||
onMSFStatusChange(arg1: number, arg2: number): void;
|
||||
|
||||
onMSFSsoError(args: unknown): void;
|
||||
|
||||
getGroupCode(args: unknown): void;
|
||||
}
|
||||
|
||||
export interface NodeIDependsAdapter extends IDependsAdapter {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(adapter: IDependsAdapter): NodeIDependsAdapter;
|
||||
}
|
||||
|
||||
export class DependsAdapter implements IDependsAdapter {
|
||||
onMSFStatusChange(arg1: number, arg2: number) {
|
||||
// console.log(arg1, arg2);
|
||||
// if (arg1 == 2 && arg2 == 2) {
|
||||
// log("NapCat丢失网络连接,请检查网络")
|
||||
// }
|
||||
}
|
||||
|
||||
onMSFSsoError(args: unknown) {
|
||||
}
|
||||
|
||||
getGroupCode(args: unknown) {
|
||||
}
|
||||
}
|
||||
23
src/core/src/adapters/NodeIDispatcherAdapter.ts
Normal file
23
src/core/src/adapters/NodeIDispatcherAdapter.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
interface IDispatcherAdapter {
|
||||
dispatchRequest(arg: unknown): void;
|
||||
|
||||
dispatchCall(arg: unknown): void;
|
||||
|
||||
dispatchCallWithJson(arg: unknown): void;
|
||||
}
|
||||
|
||||
export interface NodeIDispatcherAdapter extends IDispatcherAdapter {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(adapter: IDispatcherAdapter): NodeIDispatcherAdapter;
|
||||
}
|
||||
|
||||
export class DispatcherAdapter implements IDispatcherAdapter {
|
||||
dispatchRequest(arg: unknown) {
|
||||
}
|
||||
|
||||
dispatchCall(arg: unknown) {
|
||||
}
|
||||
|
||||
dispatchCallWithJson(arg: unknown) {
|
||||
}
|
||||
}
|
||||
48
src/core/src/adapters/NodeIGlobalAdapter.ts
Normal file
48
src/core/src/adapters/NodeIGlobalAdapter.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
interface IGlobalAdapter {
|
||||
onLog(...args: unknown[]): void;
|
||||
|
||||
onGetSrvCalTime(...args: unknown[]): void;
|
||||
|
||||
onShowErrUITips(...args: unknown[]): void;
|
||||
|
||||
fixPicImgType(...args: unknown[]): void;
|
||||
|
||||
getAppSetting(...args: unknown[]): void;
|
||||
|
||||
onInstallFinished(...args: unknown[]): void;
|
||||
|
||||
onUpdateGeneralFlag(...args: unknown[]): void;
|
||||
|
||||
onGetOfflineMsg(...args: unknown[]): void;
|
||||
}
|
||||
|
||||
export interface NodeIGlobalAdapter extends IGlobalAdapter {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(adapter: IGlobalAdapter): NodeIGlobalAdapter;
|
||||
}
|
||||
|
||||
export class GlobalAdapter implements IGlobalAdapter {
|
||||
onLog(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGetSrvCalTime(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onShowErrUITips(...args: unknown[]) {
|
||||
}
|
||||
|
||||
fixPicImgType(...args: unknown[]) {
|
||||
}
|
||||
|
||||
getAppSetting(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onInstallFinished(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onUpdateGeneralFlag(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGetOfflineMsg(...args: unknown[]) {
|
||||
}
|
||||
}
|
||||
3
src/core/src/adapters/index.ts
Normal file
3
src/core/src/adapters/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './NodeIDependsAdapter';
|
||||
export * from './NodeIDispatcherAdapter';
|
||||
export * from './NodeIGlobalAdapter';
|
||||
53
src/core/src/apis/collection.ts
Normal file
53
src/core/src/apis/collection.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { napCatCore } from "..";
|
||||
|
||||
export class NTQQCollectionApi {
|
||||
static async createCollection(authorUin: string, authorUid: string, authorName: string, brief: string, rawData: string) {
|
||||
let param = {
|
||||
commInfo: {
|
||||
bid: 1,
|
||||
category: 2,
|
||||
author: {
|
||||
type: 1,
|
||||
numId: authorUin,
|
||||
strId: authorName,
|
||||
groupId: '0',
|
||||
groupName: '',
|
||||
uid: authorUid
|
||||
},
|
||||
customGroupId: '0',
|
||||
createTime: Date.now().toString(),
|
||||
sequence: Date.now().toString()
|
||||
},
|
||||
richMediaSummary: {
|
||||
originalUri: '',
|
||||
publisher: '',
|
||||
richMediaVersion: 0,
|
||||
subTitle: '',
|
||||
title: '',
|
||||
brief: brief,
|
||||
picList: [],
|
||||
contentType: 1
|
||||
},
|
||||
richMediaContent: {
|
||||
rawData: rawData,
|
||||
bizDataList: [],
|
||||
picList: [],
|
||||
fileList: []
|
||||
},
|
||||
need_share_url: false
|
||||
};
|
||||
return napCatCore.session.getCollectionService().createNewCollectionItem(param);
|
||||
}
|
||||
static async getAllCollection(category: number = 0, count: number = 50) {
|
||||
let param = {
|
||||
category: category,
|
||||
groupId: -1,
|
||||
forceSync: true,
|
||||
forceFromDb: false,
|
||||
timeStamp: "0",
|
||||
count: count,
|
||||
searchDown: true
|
||||
};
|
||||
return napCatCore.session.getCollectionService().getCollectionItemList(param);
|
||||
}
|
||||
}
|
||||
241
src/core/src/apis/file.ts
Normal file
241
src/core/src/apis/file.ts
Normal file
@@ -0,0 +1,241 @@
|
||||
import {
|
||||
CacheFileList,
|
||||
CacheFileListItem,
|
||||
CacheFileType,
|
||||
CacheScanResult,
|
||||
ChatCacheList,
|
||||
ChatCacheListItemBasic,
|
||||
ChatType,
|
||||
ElementType, IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT, RawMessage
|
||||
} from '@/core/entities';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import fsPromises from 'fs/promises';
|
||||
import { log, logDebug, logError } from '@/common/utils/log';
|
||||
import { GeneralCallResult, napCatCore, OnRichMediaDownloadCompleteParams } from '@/core';
|
||||
import { calculateFileMD5 } from '@/common/utils/file';
|
||||
import * as fileType from 'file-type';
|
||||
import { MsgListener } from '@/core/listeners';
|
||||
import imageSize from 'image-size';
|
||||
import { ISizeCalculationResult } from 'image-size/dist/types/interface';
|
||||
import { sessionConfig } from '@/core/sessionConfig';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { rkeyManager } from '../utils/rkey';
|
||||
import { AsyncQueue } from '@/common/utils/AsyncQueue';
|
||||
// const rkeyExpireTime = 1000;
|
||||
|
||||
const getRKeyTaskQueue = new AsyncQueue();
|
||||
|
||||
const downloadMediaTasks: Map<string, (arg: OnRichMediaDownloadCompleteParams) => void> = new Map<string, (arg: OnRichMediaDownloadCompleteParams) => void>();
|
||||
|
||||
const downloadMediaListener = new MsgListener();
|
||||
downloadMediaListener.onRichMediaDownloadComplete = arg => {
|
||||
for (const [uuid, cb] of downloadMediaTasks) {
|
||||
cb(arg);
|
||||
downloadMediaTasks.delete(uuid);
|
||||
}
|
||||
};
|
||||
setTimeout(() => {
|
||||
napCatCore.onLoginSuccess(() => {
|
||||
napCatCore.addListener(downloadMediaListener);
|
||||
});
|
||||
}, 100);
|
||||
export class NTQQFileApi {
|
||||
static async getFileType(filePath: string) {
|
||||
return fileType.fileTypeFromFile(filePath);
|
||||
}
|
||||
|
||||
static async copyFile(filePath: string, destPath: string) {
|
||||
await napCatCore.util.copyFile(filePath, destPath);
|
||||
}
|
||||
|
||||
static async getFileSize(filePath: string): Promise<number> {
|
||||
return await napCatCore.util.getFileSize(filePath);
|
||||
}
|
||||
static async getVideoUrl(msg: RawMessage, element: any) {
|
||||
return (await napCatCore.session.getRichMediaService().getVideoPlayUrlV2({
|
||||
chatType: msg.chatType,
|
||||
peerUid: msg.peerUid,
|
||||
guildId: '0'
|
||||
}, msg.msgId, element.elementId, 0, { downSourceType: 1, triggerType: 1 })).urlResult.domainUrl[0].url;
|
||||
}
|
||||
// 上传文件到QQ的文件夹
|
||||
static async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) {
|
||||
// napCatCore.wrapper.util.
|
||||
const fileMd5 = await calculateFileMD5(filePath);
|
||||
let ext: string = (await NTQQFileApi.getFileType(filePath))?.ext as string || '';
|
||||
if (ext) {
|
||||
ext = '.' + ext;
|
||||
}
|
||||
let fileName = `${path.basename(filePath)}`;
|
||||
if (fileName.indexOf('.') === -1) {
|
||||
fileName += ext;
|
||||
}
|
||||
const mediaPath = napCatCore.session.getMsgService().getRichMediaFilePathForGuild({
|
||||
md5HexStr: fileMd5,
|
||||
fileName: fileName,
|
||||
elementType: elementType,
|
||||
elementSubType,
|
||||
thumbSize: 0,
|
||||
needCreate: true,
|
||||
downloadType: 1,
|
||||
file_uuid: ''
|
||||
});
|
||||
await NTQQFileApi.copyFile(filePath, mediaPath!);
|
||||
const fileSize = await NTQQFileApi.getFileSize(filePath);
|
||||
return {
|
||||
md5: fileMd5,
|
||||
fileName,
|
||||
path: mediaPath,
|
||||
fileSize,
|
||||
ext
|
||||
};
|
||||
}
|
||||
|
||||
static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
||||
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
||||
// 用于下载收到的消息中的图片等
|
||||
if (sourcePath && fs.existsSync(sourcePath)) {
|
||||
if (force) {
|
||||
try {
|
||||
await fsPromises.unlink(sourcePath);
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
} else {
|
||||
return sourcePath;
|
||||
}
|
||||
}
|
||||
//logDebug('start downloadMedia', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
let completed = false;
|
||||
const cb = (arg: OnRichMediaDownloadCompleteParams) => {
|
||||
//logDebug('downloadMedia complete', arg, msgId);
|
||||
if (arg.msgId === msgId) {
|
||||
completed = true;
|
||||
let filePath = arg.filePath;
|
||||
if (filePath.startsWith('\\')) {
|
||||
// log('filePath start with \\');
|
||||
const downloadPath = sessionConfig.defaultFileDownloadPath;
|
||||
//logDebug('downloadPath', downloadPath);
|
||||
filePath = path.join(downloadPath, filePath);
|
||||
// 下载路径是下载文件夹的相对路径
|
||||
}
|
||||
resolve(filePath);
|
||||
}
|
||||
};
|
||||
downloadMediaTasks.set(randomUUID(), cb);
|
||||
setTimeout(() => {
|
||||
if (!completed) {
|
||||
reject('下载超时');
|
||||
}
|
||||
}, timeout);
|
||||
napCatCore.session.getMsgService().downloadRichMedia({
|
||||
fileModelId: '0',
|
||||
downloadSourceType: 0,
|
||||
triggerType: 1,
|
||||
msgId: msgId,
|
||||
chatType: chatType,
|
||||
peerUid: peerUid,
|
||||
elementId: elementId,
|
||||
thumbSize: 0,
|
||||
downloadType: 1,
|
||||
filePath: thumbPath,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static async getImageSize(filePath: string): Promise<ISizeCalculationResult | undefined> {
|
||||
return new Promise((resolve, reject) => {
|
||||
imageSize(filePath, (err, dimensions) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(dimensions);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static async getImageUrl(element: { originImageUrl: any; md5HexStr?: any; fileUuid: any; }, isPrivateImage: boolean) {
|
||||
|
||||
if (!element) {
|
||||
return '';
|
||||
}
|
||||
const url = element.originImageUrl; // 没有域名
|
||||
const md5HexStr = element.md5HexStr;
|
||||
const fileMd5 = element.md5HexStr;
|
||||
const fileUuid = element.fileUuid;
|
||||
|
||||
if (url) {
|
||||
if (url.startsWith('/download')) {
|
||||
if (url.includes('&rkey=')) {
|
||||
return IMAGE_HTTP_HOST_NT + url;
|
||||
}
|
||||
|
||||
const rkeyData = await rkeyManager.getRkey();
|
||||
|
||||
const existsRKey = isPrivateImage ? rkeyData.private_rkey : rkeyData.group_rkey;
|
||||
return IMAGE_HTTP_HOST_NT + url + `${existsRKey}`;
|
||||
} else {
|
||||
// 老的图片url,不需要rkey
|
||||
return IMAGE_HTTP_HOST + url;
|
||||
}
|
||||
} else if (fileMd5 || md5HexStr) {
|
||||
// 没有url,需要自己拼接
|
||||
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 || md5HexStr)!.toUpperCase()}/0`;
|
||||
}
|
||||
logDebug('图片url获取失败', element);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export class NTQQFileCacheApi {
|
||||
static async setCacheSilentScan(isSilent: boolean = true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
static getCacheSessionPathList() {
|
||||
return '';
|
||||
}
|
||||
|
||||
static clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
|
||||
// 参数未验证
|
||||
return napCatCore.session.getStorageCleanService().clearCacheDataByKeys(cacheKeys);
|
||||
}
|
||||
|
||||
static addCacheScannedPaths(pathMap: object = {}) {
|
||||
return napCatCore.session.getStorageCleanService().addCacheScanedPaths(pathMap);
|
||||
}
|
||||
|
||||
static scanCache(): Promise<GeneralCallResult & {
|
||||
size: string[]
|
||||
}> {
|
||||
// 需要注册Listener onFinishScan
|
||||
return napCatCore.session.getStorageCleanService().scanCache();
|
||||
}
|
||||
|
||||
static getHotUpdateCachePath() {
|
||||
// 未实现
|
||||
return '';
|
||||
}
|
||||
|
||||
static getDesktopTmpPath() {
|
||||
// 未实现
|
||||
return '';
|
||||
}
|
||||
|
||||
static getChatCacheList(type: ChatType, pageSize: number = 1000, pageIndex: number = 0) {
|
||||
return napCatCore.session.getStorageCleanService().getChatCacheInfo(type, pageSize, 1, pageIndex);
|
||||
}
|
||||
|
||||
static getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
|
||||
const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
|
||||
//需要五个参数
|
||||
//return napCatCore.session.getStorageCleanService().getFileCacheInfo();
|
||||
}
|
||||
|
||||
static async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
|
||||
return napCatCore.session.getStorageCleanService().clearChatCacheInfo(chats, fileKeys);
|
||||
}
|
||||
}
|
||||
41
src/core/src/apis/friend.ts
Normal file
41
src/core/src/apis/friend.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { FriendRequest, User } from '@/core/entities';
|
||||
import { napCatCore, OnBuddyChangeParams } from '@/core';
|
||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||
|
||||
export class NTQQFriendApi {
|
||||
static async isBuddy(uid: string) {
|
||||
return napCatCore.session.getBuddyService().isBuddy(uid);
|
||||
}
|
||||
static async getFriends(forced = false): Promise<User[]> {
|
||||
let [_retData, _BuddyArg] = await NTEventDispatch.CallNormalEvent
|
||||
<(force: boolean) => Promise<any>, (arg: OnBuddyChangeParams) => void>
|
||||
(
|
||||
'NodeIKernelBuddyService/getBuddyList',
|
||||
'NodeIKernelBuddyListener/onBuddyListChange',
|
||||
1,
|
||||
5000,
|
||||
forced
|
||||
);
|
||||
const friends: User[] = [];
|
||||
for (const categoryItem of _BuddyArg) {
|
||||
for (const friend of categoryItem.buddyList) {
|
||||
friends.push(friend);
|
||||
}
|
||||
}
|
||||
return friends;
|
||||
}
|
||||
|
||||
static async handleFriendRequest(flag: string, accept: boolean) {
|
||||
let data = flag.split('|');
|
||||
if (data.length < 2) {
|
||||
return;
|
||||
}
|
||||
let friendUid = data[0];
|
||||
let reqTime = data[1];
|
||||
napCatCore.session.getBuddyService()?.approvalFriendRequest({
|
||||
friendUid: friendUid,
|
||||
reqTime: reqTime,
|
||||
accept
|
||||
});
|
||||
}
|
||||
}
|
||||
189
src/core/src/apis/group.ts
Normal file
189
src/core/src/apis/group.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
import { GroupMember, GroupRequestOperateTypes, GroupMemberRole, GroupNotify, Group, MemberExtSourceType } from '../entities';
|
||||
import { GeneralCallResult, NTQQUserApi, napCatCore } from '@/core';
|
||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||
import { logDebug } from '@/common/utils/log';
|
||||
// console.log(process.pid);
|
||||
// setTimeout(async () => {
|
||||
// console.log(JSON.stringify(await NTQQGroupApi.getMemberExtInfo(), null, 2));
|
||||
// }, 20000);
|
||||
export class NTQQGroupApi {
|
||||
static async getGroups(forced = false) {
|
||||
let [_retData, _updateType, groupList] = await NTEventDispatch.CallNormalEvent
|
||||
<(force: boolean) => Promise<any>, (updateType: number, groupList: Group[]) => void>
|
||||
(
|
||||
'NodeIKernelGroupService/getGroupList',
|
||||
'NodeIKernelGroupListener/onGroupListUpdate',
|
||||
1,
|
||||
5000,
|
||||
forced
|
||||
);
|
||||
return groupList;
|
||||
}
|
||||
static async getGroupRecommendContactArkJson(GroupCode: string) {
|
||||
return napCatCore.session.getGroupService().getGroupRecommendContactArkJson(GroupCode);
|
||||
}
|
||||
static async CreatGroupFileFolder(groupCode: string, folderName: string) {
|
||||
return napCatCore.session.getRichMediaService().createGroupFolder(groupCode, folderName);
|
||||
}
|
||||
static async DelGroupFile(groupCode: string, files: string[]) {
|
||||
return napCatCore.session.getRichMediaService().deleteGroupFile(groupCode, [102], files);
|
||||
}
|
||||
static async DelGroupFileFolder(groupCode: string, folderId: string) {
|
||||
return napCatCore.session.getRichMediaService().deleteGroupFolder(groupCode, folderId);
|
||||
}
|
||||
static async getSingleScreenNotifies(num: number) {
|
||||
let [_retData, _doubt, _seq, notifies] = await NTEventDispatch.CallNormalEvent
|
||||
<(arg1: boolean, arg2: string, arg3: number) => Promise<any>, (doubt: boolean, seq: string, notifies: GroupNotify[]) => void>
|
||||
(
|
||||
'NodeIKernelGroupService/getSingleScreenNotifies',
|
||||
'NodeIKernelGroupListener/onGroupSingleScreenNotifies',
|
||||
1,
|
||||
5000,
|
||||
false,
|
||||
'',
|
||||
num
|
||||
);
|
||||
return notifies;
|
||||
}
|
||||
static async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
||||
const groupService = napCatCore.session.getGroupService();
|
||||
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
||||
const result = await groupService.getNextMemberList(sceneId!, undefined, num);
|
||||
if (result.errCode !== 0) {
|
||||
throw ('获取群成员列表出错,' + result.errMsg);
|
||||
}
|
||||
//logDebug(`获取群(${groupQQ})成员列表结果:`, `finish: ${result.result.finish}`); //, Array.from(result.result.infos.values()));
|
||||
return result.result.infos;
|
||||
/*
|
||||
console.log(sceneId);
|
||||
const result = await napCatCore.getGroupService().getNextMemberList(sceneId, num);
|
||||
console.log(result);
|
||||
|
||||
return result;
|
||||
*/
|
||||
}
|
||||
|
||||
static async getGroupNotifies() {
|
||||
// 获取管理员变更
|
||||
// 加群通知,退出通知,需要管理员权限
|
||||
|
||||
}
|
||||
static async GetGroupFileCount(Gids: Array<string>) {
|
||||
return napCatCore.session.getRichMediaService().batchGetGroupFileCount(Gids);
|
||||
}
|
||||
static async getGroupIgnoreNotifies() {
|
||||
}
|
||||
static async getArkJsonGroupShare(GroupCode: string) {
|
||||
let ret = await NTEventDispatch.CallNoListenerEvent
|
||||
<(GroupId: string) => Promise<GeneralCallResult & { arkJson: string }>>(
|
||||
'NodeIKernelGroupService/getGroupRecommendContactArkJson',
|
||||
5000,
|
||||
GroupCode
|
||||
);
|
||||
return ret.arkJson;
|
||||
}
|
||||
//需要异常处理
|
||||
static async uploadGroupBulletinPic(GroupCode: string, imageurl: string) {
|
||||
const _Pskey = (await NTQQUserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
||||
return napCatCore.session.getGroupService().uploadGroupBulletinPic(GroupCode, _Pskey, imageurl);
|
||||
}
|
||||
static async handleGroupRequest(notify: GroupNotify, operateType: GroupRequestOperateTypes, reason?: string) {
|
||||
return napCatCore.session.getGroupService().operateSysNotify(
|
||||
false,
|
||||
{
|
||||
'operateType': operateType, // 2 拒绝
|
||||
'targetMsg': {
|
||||
'seq': notify.seq, // 通知序列号
|
||||
'type': notify.type,
|
||||
'groupCode': notify.group.groupCode,
|
||||
'postscript': reason || ''
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static async quitGroup(groupQQ: string) {
|
||||
return napCatCore.session.getGroupService().quitGroup(groupQQ);
|
||||
}
|
||||
|
||||
static async kickMember(groupQQ: string, kickUids: string[], refuseForever: boolean = false, kickReason: string = '') {
|
||||
return napCatCore.session.getGroupService().kickMember(groupQQ, kickUids, refuseForever, kickReason);
|
||||
}
|
||||
|
||||
static async banMember(groupQQ: string, memList: Array<{ uid: string, timeStamp: number }>) {
|
||||
// timeStamp为秒数, 0为解除禁言
|
||||
return napCatCore.session.getGroupService().setMemberShutUp(groupQQ, memList);
|
||||
}
|
||||
|
||||
static async banGroup(groupQQ: string, shutUp: boolean) {
|
||||
return napCatCore.session.getGroupService().setGroupShutUp(groupQQ, shutUp);
|
||||
}
|
||||
|
||||
static async setMemberCard(groupQQ: string, memberUid: string, cardName: string) {
|
||||
return napCatCore.session.getGroupService().modifyMemberCardName(groupQQ, memberUid, cardName);
|
||||
}
|
||||
|
||||
static async setMemberRole(groupQQ: string, memberUid: string, role: GroupMemberRole) {
|
||||
return napCatCore.session.getGroupService().modifyMemberRole(groupQQ, memberUid, role);
|
||||
}
|
||||
|
||||
static async setGroupName(groupQQ: string, groupName: string) {
|
||||
return napCatCore.session.getGroupService().modifyGroupName(groupQQ, groupName, false);
|
||||
}
|
||||
|
||||
// 头衔不可用
|
||||
static async setGroupTitle(groupQQ: string, uid: string, title: string) {
|
||||
|
||||
}
|
||||
|
||||
static async publishGroupBulletin(groupQQ: string, content: string, picInfo: { id: string, width: number, height: number } | undefined = undefined, pinned: number = 0, confirmRequired: number = 0,) {
|
||||
const _Pskey = (await NTQQUserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com');
|
||||
//text是content内容url编码
|
||||
let data = {
|
||||
text: encodeURI(content),
|
||||
picInfo: picInfo,
|
||||
oldFeedsId: '',
|
||||
pinned: pinned,
|
||||
confirmRequired: confirmRequired
|
||||
};
|
||||
return napCatCore.session.getGroupService().publishGroupBulletin(groupQQ, _Pskey!, data);
|
||||
}
|
||||
static async getGroupRemainAtTimes(GroupCode: string) {
|
||||
napCatCore.session.getGroupService().getGroupRemainAtTimes(GroupCode);
|
||||
}
|
||||
static async getMemberExtInfo(groupCode: string, uin: string) {
|
||||
// 仅NTQQ 9.9.11 24568测试 容易炸开谨慎使用
|
||||
return napCatCore.session.getGroupService().getMemberExtInfo(
|
||||
{
|
||||
groupCode: groupCode,
|
||||
sourceType: MemberExtSourceType.TITLETYPE,
|
||||
beginUin: '0',
|
||||
dataTime: '0',
|
||||
uinList: [uin],
|
||||
uinNum: '',
|
||||
seq: '',
|
||||
groupType: '',
|
||||
richCardNameVer: '',
|
||||
memberExtFilter: {
|
||||
memberLevelInfoUin: 1,
|
||||
memberLevelInfoPoint: 1,
|
||||
memberLevelInfoActiveDay: 1,
|
||||
memberLevelInfoLevel: 1,
|
||||
memberLevelInfoName: 1,
|
||||
levelName: 1,
|
||||
dataTime: 1,
|
||||
userShowFlag: 1,
|
||||
sysShowFlag: 1,
|
||||
timeToUpdate: 1,
|
||||
nickName: 1,
|
||||
specialTitle: 1,
|
||||
levelNameNew: 1,
|
||||
userShowFlagNew: 1,
|
||||
msgNeedField: 1,
|
||||
cmdUinFlagExt3Grocery: 1,
|
||||
memberIcon: 1,
|
||||
memberInfoSeq: 1
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
8
src/core/src/apis/index.ts
Normal file
8
src/core/src/apis/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export * from './file';
|
||||
export * from './friend';
|
||||
export * from './group';
|
||||
export * from './msg';
|
||||
export * from './user';
|
||||
export * from './webapi';
|
||||
export * from './sign';
|
||||
export * from './system';
|
||||
231
src/core/src/apis/msg.ts
Normal file
231
src/core/src/apis/msg.ts
Normal file
@@ -0,0 +1,231 @@
|
||||
import { GetFileListParam, Peer, RawMessage, SendMessageElement } from '@/core/entities';
|
||||
import { selfInfo } from '@/core/data';
|
||||
import { log, logError } from '@/common/utils/log';
|
||||
import { sleep } from '@/common/utils/helper';
|
||||
import { napCatCore } from '@/core';
|
||||
import { MsgListener, onGroupFileInfoUpdateParamType } from '@/core/listeners';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
|
||||
const sendMessagePool: Record<string, ((sendSuccessMsg: RawMessage) => void | Promise<void>) | null> = {};// peerUid: callbackFunc
|
||||
|
||||
const sendSuccessCBMap: Record<string, ((sendSuccessMsg: RawMessage) => boolean | Promise<boolean>) | null> = {};// uuid: callbackFunc
|
||||
|
||||
const GroupFileInfoUpdateTasks: Map<string, ((groupFileListResult: onGroupFileInfoUpdateParamType) => void)> = new Map();
|
||||
|
||||
const sentMsgTasks: Map<string, (msg: RawMessage) => void> = new Map();
|
||||
|
||||
const msgListener = new MsgListener();
|
||||
|
||||
msgListener.onGroupFileInfoUpdate = (groupFileListResult: onGroupFileInfoUpdateParamType) => {
|
||||
for (const [uuid, cb] of GroupFileInfoUpdateTasks) {
|
||||
cb(groupFileListResult);
|
||||
GroupFileInfoUpdateTasks.delete(uuid);
|
||||
}
|
||||
};
|
||||
|
||||
msgListener.onAddSendMsg = (msgRecord: RawMessage) => {
|
||||
// console.log("sent msg", msgRecord, sendMessagePool);
|
||||
for (const [uuid, cb] of sentMsgTasks) {
|
||||
cb(msgRecord);
|
||||
sentMsgTasks.delete(uuid);
|
||||
}
|
||||
if (sendMessagePool[msgRecord.peerUid]) {
|
||||
const r = sendMessagePool[msgRecord.peerUid]?.(msgRecord);
|
||||
if (r instanceof Promise) {
|
||||
r.then().catch(logError);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
msgListener.onMsgInfoListUpdate = (msgInfoList: RawMessage[]) => {
|
||||
msgInfoList.forEach(msg => {
|
||||
new Promise((resolve, reject) => {
|
||||
for (const cbId in sendSuccessCBMap) {
|
||||
const cb = sendSuccessCBMap[cbId]!;
|
||||
const cbResult = cb(msg);
|
||||
const checkResult = (result: boolean) => {
|
||||
if (result) {
|
||||
delete sendSuccessCBMap[cbId];
|
||||
}
|
||||
};
|
||||
if (cbResult instanceof Promise) {
|
||||
cbResult.then(checkResult);
|
||||
} else {
|
||||
checkResult(cbResult);
|
||||
}
|
||||
}
|
||||
}).then().catch(log);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
napCatCore.onLoginSuccess(() => {
|
||||
napCatCore.addListener(msgListener);
|
||||
});
|
||||
}, 100);
|
||||
|
||||
|
||||
export class NTQQMsgApi {
|
||||
// static napCatCore: NapCatCore | null = null;
|
||||
// enum BaseEmojiType {
|
||||
// NORMAL_EMOJI,
|
||||
// SUPER_EMOJI,
|
||||
// RANDOM_SUPER_EMOJI,
|
||||
// CHAIN_SUPER_EMOJI,
|
||||
// EMOJI_EMOJI
|
||||
// }
|
||||
static async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) {
|
||||
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
|
||||
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid
|
||||
// 其实以官方文档为准是最好的,https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType
|
||||
emojiId = emojiId.toString();
|
||||
return napCatCore.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set);
|
||||
}
|
||||
static async getMultiMsg(peer: Peer, rootMsgId: string, parentMsgId: string): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[]
|
||||
} | undefined> {
|
||||
return napCatCore.session.getMsgService().getMultiMsg(peer, rootMsgId, parentMsgId);
|
||||
}
|
||||
|
||||
static async getMsgsByMsgId(peer: Peer, msgIds: string[]) {
|
||||
return await napCatCore.session.getMsgService().getMsgsByMsgId(peer, msgIds);
|
||||
}
|
||||
static async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
||||
return await napCatCore.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
||||
}
|
||||
|
||||
static async activateChat(peer: Peer) {
|
||||
// await this.fetchRecentContact();
|
||||
// await sleep(500);
|
||||
}
|
||||
|
||||
static async activateChatAndGetHistory(peer: Peer) {
|
||||
|
||||
}
|
||||
static async setMsgRead(peer: Peer) {
|
||||
return napCatCore.session.getMsgService().setMsgRead(peer);
|
||||
}
|
||||
static async getGroupFileList(GroupCode: string, params: GetFileListParam) {
|
||||
return new Promise<Array<any>>(async (resolve, reject) => {
|
||||
let complete = false;
|
||||
setTimeout(() => {
|
||||
if (!complete) {
|
||||
reject('获取群文件列表超时');
|
||||
}
|
||||
}, 5000);
|
||||
const GroupFileInfoUpdateCB = (groupFileListResult: onGroupFileInfoUpdateParamType) => {
|
||||
complete = true;
|
||||
resolve(groupFileListResult.item);
|
||||
};
|
||||
GroupFileInfoUpdateTasks.set(randomUUID(), GroupFileInfoUpdateCB);
|
||||
await napCatCore.session.getRichMediaService().getGroupFileList(GroupCode, params);
|
||||
});
|
||||
}
|
||||
static async getMsgHistory(peer: Peer, msgId: string, count: number) {
|
||||
// 消息时间从旧到新
|
||||
return napCatCore.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, true);
|
||||
}
|
||||
|
||||
static async fetchRecentContact() {
|
||||
|
||||
}
|
||||
|
||||
static async recallMsg(peer: Peer, msgIds: string[]) {
|
||||
await napCatCore.session.getMsgService().recallMsg({
|
||||
chatType: peer.chatType,
|
||||
peerUid: peer.peerUid
|
||||
}, msgIds);
|
||||
}
|
||||
|
||||
static async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000): Promise<RawMessage> {
|
||||
const peerUid = peer.peerUid;
|
||||
// 等待上一个相同的peer发送完
|
||||
let checkLastSendUsingTime = 0;
|
||||
const waitLastSend: () => Promise<void> = async () => {
|
||||
if (checkLastSendUsingTime > timeout) {
|
||||
throw ('发送超时');
|
||||
}
|
||||
const lastSending = sendMessagePool[peer.peerUid];
|
||||
if (lastSending) {
|
||||
// log("有正在发送的消息,等待中...")
|
||||
await sleep(500);
|
||||
checkLastSendUsingTime += 500;
|
||||
return await waitLastSend();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
await waitLastSend();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let completed = false;
|
||||
let sentMessage: RawMessage | null = null;
|
||||
const sendSuccessCBId = randomUUID() as string;
|
||||
sendSuccessCBMap[sendSuccessCBId] = (msgRecord: RawMessage) => {
|
||||
if (msgRecord.msgId === sentMessage?.msgId) {
|
||||
if (msgRecord.sendStatus === 2) {
|
||||
delete sendSuccessCBMap[sendSuccessCBId];
|
||||
completed = true;
|
||||
resolve(msgRecord);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
sendMessagePool[peerUid] = async (rawMessage: RawMessage) => {
|
||||
// console.log('收到sent 消息', rawMessage.msgId);
|
||||
delete sendMessagePool[peerUid];
|
||||
sentMessage = rawMessage;
|
||||
};
|
||||
setTimeout(() => {
|
||||
if (completed) return;
|
||||
delete sendMessagePool[peerUid];
|
||||
delete sendSuccessCBMap[sendSuccessCBId];
|
||||
reject('发送超时');
|
||||
}, timeout);
|
||||
const result = napCatCore.session.getMsgService().sendMsg('0', peer, msgElements, new Map());
|
||||
});
|
||||
}
|
||||
|
||||
static async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
||||
return napCatCore.session.getMsgService().forwardMsg(msgIds, srcPeer, [destPeer], new Map());
|
||||
}
|
||||
|
||||
static async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise<RawMessage> {
|
||||
const msgInfos = msgIds.map(id => {
|
||||
return { msgId: id, senderShowName: selfInfo.nick };
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let complete = false;
|
||||
const onSentCB = (msg: RawMessage) => {
|
||||
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;
|
||||
resolve(msg);
|
||||
}
|
||||
};
|
||||
sentMsgTasks.set(randomUUID(), onSentCB);
|
||||
setTimeout(() => {
|
||||
if (!complete) {
|
||||
reject('转发消息超时');
|
||||
}
|
||||
}, 5000);
|
||||
napCatCore.session.getMsgService().multiForwardMsgWithComment(msgInfos, srcPeer, destPeer, [], new Map());
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
271
src/core/src/apis/sign.ts
Normal file
271
src/core/src/apis/sign.ts
Normal file
@@ -0,0 +1,271 @@
|
||||
import { logDebug } from '@/common/utils/log';
|
||||
import { NTQQUserApi } from './user';
|
||||
import { selfInfo } from '../data';
|
||||
import { RequestUtil } from '@/common/utils/request';
|
||||
import { WebApi } from './webapi';
|
||||
import { checkFileReceived, checkFileReceived2, uri2local } from '@/common/utils/file';
|
||||
import fs from 'node:fs'
|
||||
import { sleep } from '@/common/utils/helper';
|
||||
export interface IdMusicSignPostData {
|
||||
type: 'qq' | '163',
|
||||
id: string | number,
|
||||
}
|
||||
|
||||
export interface CustomMusicSignPostData {
|
||||
type: 'custom',
|
||||
url: string,
|
||||
audio: string,
|
||||
title: string,
|
||||
image?: string,
|
||||
singer?: string
|
||||
}
|
||||
|
||||
// export class MusicSign {
|
||||
// private readonly url: string;
|
||||
|
||||
// constructor(url: string) {
|
||||
// this.url = url;
|
||||
// }
|
||||
|
||||
// sign(postData: CustomMusicSignPostData | IdMusicSignPostData): Promise<any> {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// fetch(this.url, {
|
||||
// method: 'POST', // 指定请求方法为 POST
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json' // 设置请求头,指明发送的数据类型为 JSON
|
||||
// },
|
||||
// body: JSON.stringify(postData) // 将 JavaScript 对象转换为 JSON 字符串作为请求体
|
||||
// })
|
||||
// .then(response => {
|
||||
// if (!response.ok) {
|
||||
// reject(response.statusText); // 请求失败,返回错误信息
|
||||
// }
|
||||
// return response.json(); // 解析 JSON 格式的响应体
|
||||
// })
|
||||
// .then(data => {
|
||||
// logDebug('音乐消息生成成功', data);
|
||||
// resolve(data);
|
||||
// })
|
||||
// .catch(error => {
|
||||
// reject(error);
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
export interface MiniAppLuaJsonType {
|
||||
prompt: string,
|
||||
title: string,
|
||||
preview: string,
|
||||
jumpUrl: string,
|
||||
tag: string,
|
||||
tagIcon: string,
|
||||
source: string,
|
||||
sourcelogo: string,
|
||||
}
|
||||
export async function SignMiniApp(CardData: MiniAppLuaJsonType) {
|
||||
// {
|
||||
// "app": "com.tencent.miniapp.lua",
|
||||
// "bizsrc": "tianxuan.imgJumpArk",
|
||||
// "view": "miniapp",
|
||||
// "prompt": "hi! 这里有我的日常故事,只想讲给你听",
|
||||
// "config": {
|
||||
// "type": "normal",
|
||||
// "forward": 1,
|
||||
// "autosize": 0
|
||||
// },
|
||||
// "meta": {
|
||||
// "miniapp": {
|
||||
// "title": "hi! 这里有我的日常故事,只想讲给你听",
|
||||
// "preview": "https:\/\/tianquan.gtimg.cn\/qqAIAgent\/item\/7\/square.png",
|
||||
// "jumpUrl": "https:\/\/club.vip.qq.com\/transfer?open_kuikly_info=%7B%22version%22%3A%20%221%22%2C%22src_type%22%3A%20%22web%22%2C%22kr_turbo_display%22%3A%20%221%22%2C%22page_name%22%3A%20%22vas_ai_persona_moments%22%2C%22bundle_name%22%3A%20%22vas_ai_persona_moments%22%7D&page_name=vas_ai_persona_moments&enteranceId=share&robot_uin=3889008584",
|
||||
// "tag": "QQ智能体",
|
||||
// "tagIcon": "https:\/\/tianquan.gtimg.cn\/shoal\/qqAIAgent\/3e9d70c9-d98c-45b8-80b4-79d82971b514.png",
|
||||
// "source": "QQ智能体",
|
||||
// "sourcelogo": "https:\/\/tianquan.gtimg.cn\/shoal\/qqAIAgent\/3e9d70c9-d98c-45b8-80b4-79d82971b514.png"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// token : function(url,skey){
|
||||
// var str = skey || cookie('skey') || cookie('rv2') || '',
|
||||
// hash = 5381;
|
||||
// if(url){
|
||||
// var hostname = uri(url).hostname;
|
||||
// if(hostname.indexOf('qun.qq.com') > -1 || (hostname.indexOf('qzone.qq.com') > -1 && hostname.indexOf('qun.qzone.qq.com') === -1)){
|
||||
// str = cookie('p_skey') || str;
|
||||
// }
|
||||
// }
|
||||
// for(var i = 0, len = str.length; i < len; ++i){
|
||||
// hash += (hash << 5) + str.charAt(i).charCodeAt();
|
||||
// }
|
||||
// return hash & 0x7fffffff;
|
||||
// },
|
||||
//
|
||||
|
||||
// function signToken(skey: string) {
|
||||
// let hash = 5381;
|
||||
// for (let i = 0, len = skey.length; i < len; ++i) {
|
||||
// hash += (hash << 5) + skey.charCodeAt(i);
|
||||
// }
|
||||
// return hash & 0x7fffffff;
|
||||
// }
|
||||
let signCard = {
|
||||
"app": "com.tencent.miniapp.lua",
|
||||
"bizsrc": "tianxuan.imgJumpArk",
|
||||
"view": "miniapp",
|
||||
"prompt": CardData.prompt,
|
||||
"config": {
|
||||
"type": "normal",
|
||||
"forward": 1,
|
||||
"autosize": 0
|
||||
},
|
||||
"meta": {
|
||||
"miniapp": {
|
||||
"title": CardData.title,
|
||||
"preview": (CardData.preview as string).replace(/\\/g, "\\/\\/"),
|
||||
"jumpUrl": (CardData.jumpUrl as string).replace(/\\/g, "\\/\\/"),
|
||||
"tag": CardData.tag,
|
||||
"tagIcon": (CardData.tagIcon as string).replace(/\\/g, "\\/\\/"),
|
||||
"source": CardData.source,
|
||||
"sourcelogo": (CardData.sourcelogo as string).replace(/\\/g, "\\/\\/")
|
||||
}
|
||||
}
|
||||
};
|
||||
// let signCard = {
|
||||
// "app": "com.tencent.eventshare.lua",
|
||||
// "prompt": "Bot Test",
|
||||
// "bizsrc": "tianxuan.business",
|
||||
// "meta": {
|
||||
// "eventshare": {
|
||||
// "button1URL": "https://www.bilibili.com",
|
||||
// "button1disable": false,
|
||||
// "button1title": "点我前往",
|
||||
// "button2URL": "",
|
||||
// "button2disable": false,
|
||||
// "button2title": "",
|
||||
// "buttonNum": 1,
|
||||
// "jumpURL": "https://www.bilibili.com",
|
||||
// "preview": "https://tianquan.gtimg.cn/shoal/card/9930bc4e-4a92-4da3-814f-8094a2421d9c.png",
|
||||
// "tag": "QQ集卡",
|
||||
// "tagIcon": "https://tianquan.gtimg.cn/shoal/card/c034854b-102d-40be-a545-5ca90a7c49c9.png",
|
||||
// "title": "Bot Test"
|
||||
// }
|
||||
// },
|
||||
// "config": {
|
||||
// "autosize": 0,
|
||||
// "collect": 0,
|
||||
// "ctime": 1716568575,
|
||||
// "forward": 1,
|
||||
// "height": 336,
|
||||
// "reply": 0,
|
||||
// "round": 1,
|
||||
// "type": "normal",
|
||||
// "width": 263
|
||||
// },
|
||||
// "view": "eventshare",
|
||||
// "ver": "0.0.0.1"
|
||||
// };
|
||||
let data = (await NTQQUserApi.getQzoneCookies());
|
||||
const Bkn = WebApi.genBkn(data.p_skey);
|
||||
|
||||
const CookieValue = 'p_skey=' + data.p_skey + '; skey=' + data.skey + '; p_uin=o' + selfInfo.uin + '; uin=o' + selfInfo.uin;
|
||||
|
||||
let signurl = "https://h5.qzone.qq.com/v2/vip/tx/trpc/ark-share/GenNewSignedArk?g_tk=" + Bkn + "&ark=" + encodeURIComponent(JSON.stringify(signCard));
|
||||
let signed_ark = "";
|
||||
try {
|
||||
let retData = await RequestUtil.HttpGetJson<{ code: number, data: { signed_ark: string } }>(signurl, 'GET', undefined, { Cookie: CookieValue });
|
||||
//logDebug('MiniApp JSON 消息生成成功', retData);
|
||||
signed_ark = retData.data.signed_ark;
|
||||
} catch (error) {
|
||||
logDebug('MiniApp JSON 消息生成失败', error);
|
||||
}
|
||||
return signed_ark;
|
||||
}
|
||||
export async function SignMusicInternal(songname: string, singer: string, cover: string, songmid: string, songmusic: string) {
|
||||
//curl -X POST 'https://mqq.reader.qq.com/api/mqq/share/card?accessToken&_csrfToken&source=c0003' -H 'Content-Type: application/json' -H 'Cookie: uin=o10086' -d '{"app":"com.tencent.qqreader.share","config":{"ctime":1718634110,"forward":1,"token":"9a63343c32d5a16bcde653eb97faa25d","type":"normal"},"extra":{"app_type":1,"appid":100497308,"msg_seq":14386738075403815000.0,"uin":1733139081},"meta":{"music":{"action":"","android_pkg_name":"","app_type":1,"appid":100497308,"ctime":1718634110,"desc":"周杰伦","jumpUrl":"https://i.y.qq.com/v8/playsong.html?songmid=0039MnYb0qxYhV&type=0","musicUrl":"http://ws.stream.qqmusic.qq.com/http://isure6.stream.qqmusic.qq.com/M800002202B43Cq4V4.mp3?fromtag=810033622&guid=br_xzg&trace=23fe7bcbe2336bbf&uin=553&vkey=CF0F5CE8B0FA16F3001F8A88D877A217EB5E4F00BDCEF1021EB6C48969CA33C6303987AEECE9CC840122DD2F917A59D6130D8A8CA4577C87","preview":"https://y.qq.com/music/photo_new/T002R800x800M000000MkMni19ClKG.jpg","cover":"https://y.qq.com/music/photo_new/T002R800x800M000000MkMni19ClKG.jpg","sourceMsgId":"0","source_icon":"https://p.qpic.cn/qqconnect/0/app_100497308_1626060999/100?max-age=2592000&t=0","source_url":"","tag":"QQ音乐","title":"晴天","uin":10086}},"prompt":"[分享]晴天","ver":"0.0.0.1","view":"music"}'
|
||||
let signurl = 'https://mqq.reader.qq.com/api/mqq/share/card?accessToken&_csrfToken&source=c0003';
|
||||
//let = "https://y.qq.com/music/photo_new/T002R800x800M000000MkMni19ClKG.jpg";
|
||||
let signCard = {
|
||||
app: "com.tencent.qqreader.share",
|
||||
config: {
|
||||
ctime: 1718634110,
|
||||
forward: 1,
|
||||
token: "9a63343c32d5a16bcde653eb97faa25d",
|
||||
type: "normal"
|
||||
},
|
||||
extra: {
|
||||
app_type: 1,
|
||||
appid: 100497308,
|
||||
msg_seq: 14386738075403815000.0,
|
||||
uin: 1733139081
|
||||
},
|
||||
meta: {
|
||||
music:
|
||||
{
|
||||
action: "",
|
||||
android_pkg_name: "",
|
||||
app_type: 1,
|
||||
appid: 100497308,
|
||||
ctime: 1718634110,
|
||||
desc: singer,
|
||||
jumpUrl: "https://i.y.qq.com/v8/playsong.html?songmid=" + songmid + "&type=0",
|
||||
musicUrl: songmusic,
|
||||
preview: cover,
|
||||
cover: cover,
|
||||
sourceMsgId: "0",
|
||||
source_icon: "https://p.qpic.cn/qqconnect/0/app_100497308_1626060999/100?max-age=2592000&t=0",
|
||||
source_url: "",
|
||||
tag: "QQ音乐",
|
||||
title: songname,
|
||||
uin: 10086
|
||||
}
|
||||
},
|
||||
prompt: "[分享]" + songname,
|
||||
ver: "0.0.0.1",
|
||||
view: "music"
|
||||
}
|
||||
//console.log(JSON.stringify(signCard, null, 2));
|
||||
let data = await RequestUtil.HttpGetJson<{ code: number, data: { arkResult: string } }>
|
||||
(signurl, 'POST', signCard, { 'Cookie': 'uin=o10086', 'Content-Type': 'application/json' });
|
||||
return data;
|
||||
}
|
||||
//注意处理错误
|
||||
export async function CreateMusicThridWay0(id: string = '', mid: string = '') {
|
||||
if (mid == '') {
|
||||
let MusicInfo = await RequestUtil.HttpGetJson
|
||||
<{ songinfo?: { data?: { track_info: { mid: string } } } }>
|
||||
(
|
||||
'https://u.y.qq.com/cgi-bin/musicu.fcg?format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0&data={"comm":{"ct":24,"cv":0},"songinfo":{"method":"get_song_detail_yqq","param":{"song_type":0,"song_mid":"","song_id":' + id + '},"module":"music.pf_song_detail_svr"}}',
|
||||
'GET',
|
||||
undefined
|
||||
);
|
||||
mid = MusicInfo.songinfo?.data?.track_info.mid!;
|
||||
}
|
||||
//第三方接口 存在速率限制 现在勉强用
|
||||
let MusicReal = await RequestUtil.HttpGetJson
|
||||
<{ code: number, data?: { name: string, singer: string, url: string, cover: string } }>
|
||||
('https://api.leafone.cn/api/qqmusic?id=' + mid + '&type=8', 'GET', undefined);
|
||||
//console.log(MusicReal);
|
||||
return { ...MusicReal.data, mid: mid };
|
||||
}
|
||||
export async function CreateMusicThridWay1(id: string = '', mid: string = '') {
|
||||
|
||||
}
|
||||
//转换外域名为 https://qq.ugcimg.cn/v1/cpqcbu4b8870i61bde6k7cbmjgejq8mr3in82qir4qi7ielffv5slv8ck8g42novtmev26i233ujtuab6tvu2l2sjgtupfr389191v00s1j5oh5325j5eqi40774jv1i/khovifoh7jrqd6eahoiv7koh8o
|
||||
//https://cgi.connect.qq.com/qqconnectopen/openapi/change_image_url?url=https://th.bing.com/th?id=OSK.b8ed36f1fb1889de6dc84fd81c187773&w=46&h=46&c=11&rs=1&qlt=80&o=6&dpr=2&pid=SANGAM
|
||||
|
||||
//外域名不行得走qgroup中转
|
||||
//https://proxy.gtimg.cn/tx_tls_gate=y.qq.com/music/photo_new/T002R800x800M000000y5gq7449K9I.jpg
|
||||
|
||||
//可外域名
|
||||
//https://pic.ugcimg.cn/500955bdd6657ecc8e82e02d2df06800/jpg1
|
||||
|
||||
//QQ音乐gtimg接口
|
||||
//https://y.gtimg.cn/music/photo_new/T002R800x800M000000y5gq7449K9I.jpg?max_age=2592000
|
||||
|
||||
//还有一处公告上传可以上传高质量图片 持久为qq域名
|
||||
export async function SignMusicWrapper(id: string = '') {
|
||||
let MusicInfo = await CreateMusicThridWay0(id)!;
|
||||
let MusicCard = await SignMusicInternal(MusicInfo.name!, MusicInfo.singer!, MusicInfo.cover!, MusicInfo.mid!, "https://ws.stream.qqmusic.qq.com/" + MusicInfo.url!);
|
||||
return MusicCard;
|
||||
}
|
||||
39
src/core/src/apis/system.ts
Normal file
39
src/core/src/apis/system.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
|
||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||
import { GeneralCallResult, NTQQUserApi, napCatCore } from '@/core';
|
||||
// setTimeout(async () => {
|
||||
// let ret = await NTQQSystemApi.getArkJsonCollection('1-2-162b9b42-65b9-4405-a8ed-2e256ec8aa50');
|
||||
// console.log(ret);
|
||||
// }, 20000)
|
||||
export class NTQQSystemApi {
|
||||
static async hasOtherRunningQQProcess() {
|
||||
return napCatCore.util.hasOtherRunningQQProcess();
|
||||
}
|
||||
static async ORCImage(filePath: string) {
|
||||
return napCatCore.session.getNodeMiscService().wantWinScreenOCR(filePath);
|
||||
}
|
||||
static async translateEnWordToZn(words: string[]) {
|
||||
return napCatCore.session.getRichMediaService().translateEnWordToZn(words);
|
||||
}
|
||||
//调用会超时 没灯用
|
||||
static async getOnlineDev() {
|
||||
return napCatCore.session.getMsgService().getOnLineDev();
|
||||
}
|
||||
//1-2-162b9b42-65b9-4405-a8ed-2e256ec8aa50
|
||||
static async getArkJsonCollection(cid: string) {
|
||||
let ret = await NTEventDispatch.CallNoListenerEvent
|
||||
<(cid: string) => Promise<GeneralCallResult & { arkJson: string }>>(
|
||||
'NodeIKernelCollectionService/collectionArkShare',
|
||||
5000,
|
||||
'1717662698058'
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
static async BootMiniApp(appfile: string, params: string) {
|
||||
await napCatCore.session.getNodeMiscService().setMiniAppVersion('2.16.4');
|
||||
let c = await napCatCore.session.getNodeMiscService().getMiniAppPath();
|
||||
console.log(c);
|
||||
return napCatCore.session.getNodeMiscService().startNewMiniApp(appfile, params);
|
||||
}
|
||||
}
|
||||
199
src/core/src/apis/user.ts
Normal file
199
src/core/src/apis/user.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
import { ModifyProfileParams, SelfInfo, User, UserDetailInfoByUin } from '@/core/entities';
|
||||
import { selfInfo } from '@/core/data';
|
||||
import { CacheClassFuncAsync } from '@/common/utils/helper';
|
||||
import { GeneralCallResult, napCatCore } from '@/core';
|
||||
import { ProfileListener } from '@/core/listeners';
|
||||
import { rejects } from 'assert';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { RequestUtil } from '@/common/utils/request';
|
||||
import { logDebug, logError } from '@/common/utils/log';
|
||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||
const userInfoCache: Record<string, User> = {}; // uid: User
|
||||
|
||||
const profileListener = new ProfileListener();
|
||||
|
||||
const userDetailHandlers: Map<string, ((profile: User) => void)> = new Map();
|
||||
profileListener.onProfileDetailInfoChanged = (profile) => {
|
||||
userInfoCache[profile.uid] = profile;
|
||||
userDetailHandlers.forEach(handler => handler(profile));
|
||||
};
|
||||
setTimeout(() => {
|
||||
napCatCore.onLoginSuccess(() => {
|
||||
napCatCore.addListener(profileListener);
|
||||
});
|
||||
}, 100);
|
||||
// 老版本逻辑现已移除
|
||||
// console.log('onProfileDetailInfoChanged', profile);
|
||||
// recevCount++;
|
||||
// firstProfile = profile;
|
||||
// if (recevCount === 2) {
|
||||
// profileService.removeKernelProfileListener(listenerId);
|
||||
// // if (!completed) {
|
||||
// completed = true;
|
||||
// resolve(profile);
|
||||
// // }
|
||||
// }
|
||||
// };
|
||||
export class NTQQUserApi {
|
||||
static async setLongNick(longNick: string) {
|
||||
return napCatCore.session.getProfileService().setLongNick(longNick);
|
||||
}
|
||||
static async setSelfOnlineStatus(status: number, extStatus: number, batteryStatus: number) {
|
||||
return napCatCore.session.getMsgService().setStatus({ status: status, extStatus: extStatus, batteryStatus: batteryStatus });
|
||||
}
|
||||
static async getBuddyRecommendContactArkJson(uin: string, sencenID = '') {
|
||||
return napCatCore.session.getBuddyService().getBuddyRecommendContactArkJson(uin, sencenID);
|
||||
}
|
||||
static async like(uid: string, count = 1): Promise<{ result: number, errMsg: string, succCounts: number }> {
|
||||
return napCatCore.session.getProfileLikeService().setBuddyProfileLike({
|
||||
friendUid: uid,
|
||||
sourceId: 71,
|
||||
doLikeCount: count,
|
||||
doLikeTollCount: 0
|
||||
});
|
||||
}
|
||||
|
||||
static async setQQAvatar(filePath: string) {
|
||||
type setQQAvatarRet = { result: number, errMsg: string };
|
||||
const ret = await napCatCore.session.getProfileService().setHeader(filePath) as setQQAvatarRet;
|
||||
return { result: ret?.result, errMsg: ret?.errMsg };
|
||||
}
|
||||
|
||||
static async getSelfInfo() {
|
||||
|
||||
}
|
||||
|
||||
static async getUserInfo(uid: string) {
|
||||
|
||||
}
|
||||
// enum ProfileBizType {
|
||||
// KALL,
|
||||
// KBASEEXTEND,
|
||||
// KVAS,
|
||||
// KQZONE,
|
||||
// KOTHER
|
||||
// }
|
||||
static async getUserDetailInfo(uid: string): Promise<User> {
|
||||
// const existUser = userInfoCache[uid];
|
||||
// if (existUser) {
|
||||
// return existUser;
|
||||
// }
|
||||
const profileService = napCatCore.session.getProfileService();
|
||||
// console.log('getUserDetailInfo', result);
|
||||
return new Promise((resolve, reject) => {
|
||||
const uuid = randomUUID();
|
||||
let completed = false;
|
||||
let retData: User | undefined = undefined;
|
||||
let isFirst = true;
|
||||
// 不管返回几次 超时有数据就该返回 兼容就好了
|
||||
setTimeout(() => {
|
||||
if (!completed) {
|
||||
if (retData) {
|
||||
resolve(retData);
|
||||
} else {
|
||||
reject('getUserDetailInfo timeout');
|
||||
}
|
||||
}
|
||||
userDetailHandlers.delete(uuid);
|
||||
}, 5000);
|
||||
userDetailHandlers.set(uuid, (profile) => {
|
||||
if (profile.uid === uid) {
|
||||
if (isFirst) {
|
||||
retData = profile;
|
||||
isFirst = false;
|
||||
// console.log('getUserDetailInfo', profile);
|
||||
} else {
|
||||
completed = true;
|
||||
resolve(profile);
|
||||
}
|
||||
}
|
||||
});
|
||||
profileService.getUserDetailInfoWithBizInfo(uid, [0]).then(result => {
|
||||
// console.log('getUserDetailInfo', result);
|
||||
});
|
||||
});
|
||||
}
|
||||
static async modifySelfProfile(param: ModifyProfileParams) {
|
||||
return napCatCore.session.getProfileService().modifyDesktopMiniProfile(param);
|
||||
}
|
||||
//需要异常处理
|
||||
@CacheClassFuncAsync(1800 * 1000)
|
||||
static async getCookies(domain: string) {
|
||||
const ClientKeyData = await NTQQUserApi.forceFetchClientKey();
|
||||
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + selfInfo.uin + '%2Finfocenter&keyindex=19%27'
|
||||
let cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
|
||||
return cookies;
|
||||
}
|
||||
@CacheClassFuncAsync(1800 * 1000)
|
||||
static async getPSkey(domainList: string[]) {
|
||||
return await napCatCore.session.getTipOffService().getPskey(domainList, true);
|
||||
}
|
||||
static async getRobotUinRange(): Promise<Array<any>> {
|
||||
const robotUinRanges = await napCatCore.session.getRobotService().getRobotUinRange({
|
||||
justFetchMsgConfig: '1',
|
||||
type: 1,
|
||||
version: 0,
|
||||
aioKeywordVersion: 0
|
||||
});
|
||||
// console.log(robotUinRanges?.response?.robotUinRanges);
|
||||
return robotUinRanges?.response?.robotUinRanges;
|
||||
}
|
||||
//需要异常处理
|
||||
@CacheClassFuncAsync(1800 * 1000)
|
||||
static async getQzoneCookies() {
|
||||
const ClientKeyData = await NTQQUserApi.forceFetchClientKey();
|
||||
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2Fuser.qzone.qq.com%2F' + selfInfo.uin + '%2Finfocenter&keyindex=19%27'
|
||||
let cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
|
||||
return cookies;
|
||||
}
|
||||
//需要异常处理
|
||||
@CacheClassFuncAsync(1800 * 1000)
|
||||
static async getSkey(): Promise<string | undefined> {
|
||||
const ClientKeyData = await NTQQUserApi.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=' + selfInfo.uin + '&clientkey=' + clientKey + '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=19%27';
|
||||
let cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
|
||||
const skey = cookies['skey'];
|
||||
if (!skey) {
|
||||
throw new Error('getSkey Skey is Empty');
|
||||
}
|
||||
return skey;
|
||||
}
|
||||
static async getUidByUin(Uin: string) {
|
||||
let ret = await NTEventDispatch.CallNoListenerEvent
|
||||
<(Uin: string[]) => Promise<{ uidInfo: Map<string, string> }>>(
|
||||
'NodeIKernelUixConvertService/getUid',
|
||||
5000,
|
||||
[Uin]
|
||||
);
|
||||
return ret.uidInfo.get(Uin);
|
||||
}
|
||||
static async getUinByUid(Uid: string | undefined) {
|
||||
if (!Uid) {
|
||||
return '';
|
||||
}
|
||||
let ret = await NTEventDispatch.CallNoListenerEvent
|
||||
<(Uin: string[]) => Promise<{ uinInfo: Map<string, string> }>>(
|
||||
'NodeIKernelUixConvertService/getUin',
|
||||
5000,
|
||||
[Uid]
|
||||
);
|
||||
return ret.uinInfo.get(Uid);
|
||||
}
|
||||
static async getUserDetailInfoByUin(Uin: string) {
|
||||
return NTEventDispatch.CallNoListenerEvent
|
||||
<(Uin: string) => Promise<UserDetailInfoByUin>>(
|
||||
'NodeIKernelProfileService/getUserDetailInfoByUin',
|
||||
5000,
|
||||
Uin
|
||||
);
|
||||
}
|
||||
@CacheClassFuncAsync(3600 * 1000, 'ClientKey')
|
||||
static async forceFetchClientKey() {
|
||||
return await napCatCore.session.getTicketService().forceFetchClientKey('');
|
||||
}
|
||||
}
|
||||
351
src/core/src/apis/webapi.ts
Normal file
351
src/core/src/apis/webapi.ts
Normal file
@@ -0,0 +1,351 @@
|
||||
import { selfInfo } from '@/core/data';
|
||||
import { log, logDebug } from '@/common/utils/log';
|
||||
import { NTQQUserApi } from './user';
|
||||
import { RequestUtil } from '@/common/utils/request';
|
||||
import { CacheClassFuncAsync } from '@/common/utils/helper';
|
||||
export enum WebHonorType {
|
||||
ALL = 'all',
|
||||
TALKACTIVE = 'talkative',
|
||||
PERFROMER = 'performer',
|
||||
LEGEND = 'legend',
|
||||
STORONGE_NEWBI = 'strong_newbie',
|
||||
EMOTION = 'emotion'
|
||||
}
|
||||
export interface WebApiGroupMember {
|
||||
uin: number
|
||||
role: number
|
||||
g: number
|
||||
join_time: number
|
||||
last_speak_time: number
|
||||
lv: {
|
||||
point: number
|
||||
level: number
|
||||
}
|
||||
card: string
|
||||
tags: string
|
||||
flag: number
|
||||
nick: string
|
||||
qage: number
|
||||
rm: number
|
||||
}
|
||||
interface WebApiGroupMemberRet {
|
||||
ec: number
|
||||
errcode: number
|
||||
em: string
|
||||
cache: number
|
||||
adm_num: number
|
||||
levelname: any
|
||||
mems: WebApiGroupMember[]
|
||||
count: number
|
||||
svr_time: number
|
||||
max_count: number
|
||||
search_count: number
|
||||
extmode: number
|
||||
}
|
||||
export interface WebApiGroupNoticeFeed {
|
||||
u: number//发送者
|
||||
fid: string//fid
|
||||
pubt: number//时间
|
||||
msg: {
|
||||
text: string
|
||||
text_face: string
|
||||
title: string,
|
||||
pics?: {
|
||||
id: string,
|
||||
w: string,
|
||||
h: string
|
||||
}[]
|
||||
}
|
||||
type: number
|
||||
fn: number
|
||||
cn: number
|
||||
vn: number
|
||||
settings: {
|
||||
is_show_edit_card: number
|
||||
remind_ts: number
|
||||
tip_window_type: number
|
||||
confirm_required: number
|
||||
}
|
||||
read_num: number
|
||||
is_read: number
|
||||
is_all_confirm: number
|
||||
}
|
||||
export interface WebApiGroupNoticeRet {
|
||||
ec: number
|
||||
em: string
|
||||
ltsm: number
|
||||
srv_code: number
|
||||
read_only: number
|
||||
role: number
|
||||
feeds: WebApiGroupNoticeFeed[]
|
||||
group: {
|
||||
group_id: number
|
||||
class_ext: number
|
||||
}
|
||||
sta: number,
|
||||
gln: number
|
||||
tst: number,
|
||||
ui: any
|
||||
server_time: number
|
||||
svrt: number
|
||||
ad: number
|
||||
}
|
||||
interface GroupEssenceMsg {
|
||||
group_code: string
|
||||
msg_seq: number
|
||||
msg_random: number
|
||||
sender_uin: string
|
||||
sender_nick: string
|
||||
sender_time: number
|
||||
add_digest_uin: string
|
||||
add_digest_nick: string
|
||||
add_digest_time: number
|
||||
msg_content: any[]
|
||||
can_be_removed: true
|
||||
}
|
||||
export interface GroupEssenceMsgRet {
|
||||
retcode: number
|
||||
retmsg: string
|
||||
data: {
|
||||
msg_list: GroupEssenceMsg[]
|
||||
is_end: boolean
|
||||
group_role: number
|
||||
config_page_url: string
|
||||
}
|
||||
}
|
||||
export class WebApi {
|
||||
@CacheClassFuncAsync(3600 * 1000, 'webapi_get_group_members')
|
||||
static async getGroupEssenceMsg(GroupCode: string, page_start: string) {
|
||||
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com');
|
||||
const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||
const Bkn = WebApi.genBkn(CookiesObject.skey);
|
||||
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 {
|
||||
ret = await RequestUtil.HttpGetJson<GroupEssenceMsgRet>(url, 'GET', '', { 'Cookie': CookieValue });
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
//console.log(url, CookieValue);
|
||||
if (ret.retcode !== 0) {
|
||||
return undefined;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@CacheClassFuncAsync(3600 * 1000, 'webapi_get_group_members')
|
||||
static async getGroupMembers(GroupCode: string, cached: boolean = true): Promise<WebApiGroupMember[]> {
|
||||
//logDebug('webapi 获取群成员', GroupCode);
|
||||
let MemberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>();
|
||||
try {
|
||||
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com');
|
||||
const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||
const Bkn = WebApi.genBkn(CookiesObject.skey);
|
||||
const retList: Promise<WebApiGroupMemberRet>[] = [];
|
||||
const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet>('https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?st=0&end=40&sort=1&gc=' + GroupCode + '&bkn=' + Bkn, 'POST', '', { 'Cookie': CookieValue });
|
||||
if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) {
|
||||
return [];
|
||||
} else {
|
||||
for (const key in fastRet.mems) {
|
||||
MemberData.push(fastRet.mems[key]);
|
||||
}
|
||||
}
|
||||
//初始化获取PageNum
|
||||
const PageNum = Math.ceil(fastRet.count / 40);
|
||||
//遍历批量请求
|
||||
for (let i = 2; i <= PageNum; i++) {
|
||||
const ret: Promise<WebApiGroupMemberRet> = RequestUtil.HttpGetJson<WebApiGroupMemberRet>('https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?st=' + (i - 1) * 40 + '&end=' + i * 40 + '&sort=1&gc=' + GroupCode + '&bkn=' + Bkn, 'POST', '', { 'Cookie': CookieValue });
|
||||
retList.push(ret);
|
||||
}
|
||||
//批量等待
|
||||
for (let i = 1; i <= PageNum; i++) {
|
||||
const ret = await (retList[i]);
|
||||
if (!ret?.count || ret?.errcode !== 0 || !ret?.mems) {
|
||||
continue;
|
||||
}
|
||||
for (const key in ret.mems) {
|
||||
MemberData.push(ret.mems[key]);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return MemberData;
|
||||
}
|
||||
return MemberData;
|
||||
}
|
||||
// public static async addGroupDigest(groupCode: string, msgSeq: string) {
|
||||
// const url = `https://qun.qq.com/cgi-bin/group_digest/cancel_digest?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&msg_seq=${msgSeq}&msg_random=444021292`;
|
||||
// const res = await this.request(url);
|
||||
// return await res.json();
|
||||
// }
|
||||
|
||||
// public async getGroupDigest(groupCode: string) {
|
||||
// const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&page_start=0&page_limit=20`;
|
||||
// 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}
|
||||
|
||||
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com');
|
||||
const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||
const Bkn = WebApi.genBkn(CookiesObject.skey);
|
||||
let ret: any = undefined;
|
||||
const data = 'qid=' + GroupCode + '&bkn=' + Bkn + '&text=' + Content + '&pinned=0&type=1&settings={"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}';
|
||||
const url = 'https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?bkn=' + Bkn;
|
||||
try {
|
||||
ret = await RequestUtil.HttpGetJson<any>(url, 'GET', '', { 'Cookie': CookieValue });
|
||||
return ret;
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
static async getGrouptNotice(GroupCode: string): Promise<undefined | WebApiGroupNoticeRet> {
|
||||
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com');
|
||||
const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||
const Bkn = WebApi.genBkn(CookiesObject.skey);
|
||||
let ret: WebApiGroupNoticeRet | undefined = undefined;
|
||||
//console.log(CookieValue);
|
||||
const url = 'https://web.qun.qq.com/cgi-bin/announce/get_t_list?bkn=' + Bkn + '&qid=' + GroupCode + '&ft=23&ni=1&n=1&i=1&log_read=1&platform=1&s=-1&n=20';
|
||||
try {
|
||||
ret = await RequestUtil.HttpGetJson<WebApiGroupNoticeRet>(url, 'GET', '', { 'Cookie': CookieValue });
|
||||
if (ret?.ec !== 0) {
|
||||
return undefined;
|
||||
}
|
||||
return ret;
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
static genBkn(sKey: string) {
|
||||
sKey = sKey || '';
|
||||
let hash = 5381;
|
||||
|
||||
for (let i = 0; i < sKey.length; i++) {
|
||||
const code = sKey.charCodeAt(i);
|
||||
hash = hash + (hash << 5) + code;
|
||||
}
|
||||
|
||||
return (hash & 0x7FFFFFFF).toString();
|
||||
}
|
||||
|
||||
@CacheClassFuncAsync(3600 * 1000, 'GroupHonorInfo')
|
||||
static async getGroupHonorInfo(groupCode: string, getType: WebHonorType) {
|
||||
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com');
|
||||
const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||
const Bkn = WebApi.genBkn(CookiesObject.skey);
|
||||
async function getDataInternal(Internal_groupCode: string, Internal_type: number) {
|
||||
let url = 'https://qun.qq.com/interactive/honorlist?gc=' + Internal_groupCode + '&type=' + Internal_type.toString();
|
||||
let res = '';
|
||||
let resJson;
|
||||
try {
|
||||
res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': CookieValue });
|
||||
const match = res.match(/window\.__INITIAL_STATE__=(.*?);/);
|
||||
if (match) {
|
||||
resJson = JSON.parse(match[1].trim());
|
||||
}
|
||||
if (Internal_type === 1) {
|
||||
return resJson?.talkativeList;
|
||||
} else {
|
||||
return resJson?.actorList;
|
||||
}
|
||||
} catch (e) {
|
||||
logDebug('获取当前群荣耀失败', url, e);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let HonorInfo: any = { group_id: groupCode };
|
||||
|
||||
if (getType === WebHonorType.TALKACTIVE || getType === WebHonorType.ALL) {
|
||||
try {
|
||||
let RetInternal = await getDataInternal(groupCode, 1);
|
||||
if (!RetInternal) {
|
||||
throw new Error('获取龙王信息失败');
|
||||
}
|
||||
HonorInfo.current_talkative = {
|
||||
user_id: RetInternal[0]?.uin,
|
||||
avatar: RetInternal[0]?.avatar,
|
||||
nickname: RetInternal[0]?.name,
|
||||
day_count: 0,
|
||||
description: RetInternal[0]?.desc
|
||||
}
|
||||
HonorInfo.talkative_list = [];
|
||||
for (const talkative_ele of RetInternal) {
|
||||
HonorInfo.talkative_list.push({
|
||||
user_id: talkative_ele?.uin,
|
||||
avatar: talkative_ele?.avatar,
|
||||
description: talkative_ele?.desc,
|
||||
day_count: 0,
|
||||
nickname: talkative_ele?.name
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
logDebug(e);
|
||||
}
|
||||
}
|
||||
if (getType === WebHonorType.PERFROMER || getType === WebHonorType.ALL) {
|
||||
try {
|
||||
let RetInternal = await getDataInternal(groupCode, 2);
|
||||
if (!RetInternal) {
|
||||
throw new Error('获取群聊之火失败');
|
||||
}
|
||||
HonorInfo.performer_list = [];
|
||||
for (const performer_ele of RetInternal) {
|
||||
HonorInfo.performer_list.push({
|
||||
user_id: performer_ele?.uin,
|
||||
nickname: performer_ele?.name,
|
||||
avatar: performer_ele?.avatar,
|
||||
description: performer_ele?.desc
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
logDebug(e);
|
||||
}
|
||||
}
|
||||
if (getType === WebHonorType.PERFROMER || getType === WebHonorType.ALL) {
|
||||
try {
|
||||
let RetInternal = await getDataInternal(groupCode, 3);
|
||||
if (!RetInternal) {
|
||||
throw new Error('获取群聊炽焰失败');
|
||||
}
|
||||
HonorInfo.legend_list = [];
|
||||
for (const legend_ele of RetInternal) {
|
||||
HonorInfo.legend_list.push({
|
||||
user_id: legend_ele?.uin,
|
||||
nickname: legend_ele?.name,
|
||||
avatar: legend_ele?.avatar,
|
||||
desc: legend_ele?.description
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
logDebug('获取群聊炽焰失败', e);
|
||||
}
|
||||
}
|
||||
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
||||
try {
|
||||
let RetInternal = await getDataInternal(groupCode, 6);
|
||||
if (!RetInternal) {
|
||||
throw new Error('获取快乐源泉失败');
|
||||
}
|
||||
HonorInfo.emotion_list = [];
|
||||
for (const emotion_ele of RetInternal) {
|
||||
HonorInfo.emotion_list.push({
|
||||
user_id: emotion_ele?.uin,
|
||||
nickname: emotion_ele?.name,
|
||||
avatar: emotion_ele?.avatar,
|
||||
desc: emotion_ele?.description
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
logDebug('获取快乐源泉失败', e);
|
||||
}
|
||||
}
|
||||
//冒尖小春笋好像已经被tx扬了
|
||||
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
||||
HonorInfo.strong_newbie_list = [];
|
||||
}
|
||||
return HonorInfo;
|
||||
}
|
||||
}
|
||||
478
src/core/src/core.ts
Normal file
478
src/core/src/core.ts
Normal file
@@ -0,0 +1,478 @@
|
||||
import QQWrapper, { NodeIQQNTWrapperEngine, NodeIQQNTWrapperSession, NodeQQNTWrapperUtil } from '@/core/wrapper';
|
||||
import {
|
||||
NodeIKernelLoginService,
|
||||
NodeIKernelBuddyService,
|
||||
QuickLoginResult, passwordLoginArgType
|
||||
} from '@/core/services';
|
||||
import {
|
||||
BuddyListener,
|
||||
GroupListener,
|
||||
LoginListener, MsgListener,
|
||||
ProfileListener, SessionListener
|
||||
} from '@/core/listeners';
|
||||
import { DependsAdapter, DispatcherAdapter, GlobalAdapter, NodeIGlobalAdapter } from '@/core/adapters';
|
||||
import path from 'node:path';
|
||||
import os from 'node:os';
|
||||
import fs from 'node:fs';
|
||||
import { appid, qqVersionConfigInfo } from '@/common/utils/QQBasicInfo';
|
||||
import { hostname, systemVersion } from '@/common/utils/system';
|
||||
import { genSessionConfig } from '@/core/sessionConfig';
|
||||
import { dbUtil } from '@/common/utils/db';
|
||||
import { sleep } from '@/common/utils/helper';
|
||||
import crypto from 'node:crypto';
|
||||
import { rawFriends, friends, groupMembers, groups, selfInfo, stat } from '@/core/data';
|
||||
import { RawMessage } from '@/core/entities';
|
||||
import { NTEventDispatch } from '@/common/utils/EventTask';
|
||||
import {
|
||||
enableConsoleLog,
|
||||
enableFileLog,
|
||||
log,
|
||||
logDebug,
|
||||
logError,
|
||||
setLogLevel,
|
||||
setLogSelfInfo
|
||||
} from '@/common/utils/log';
|
||||
import { napCatConfig } from '@/core/utils/config';
|
||||
|
||||
export interface OnLoginSuccess {
|
||||
(uin: string, uid: string): void | Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
export class NapCatCore {
|
||||
public readonly session: NodeIQQNTWrapperSession;
|
||||
public readonly util: NodeQQNTWrapperUtil;
|
||||
public readonly engine: NodeIQQNTWrapperEngine;
|
||||
private readonly loginListener: LoginListener;
|
||||
|
||||
private loginService: NodeIKernelLoginService;
|
||||
private onLoginSuccessFuncList: OnLoginSuccess[] = [];
|
||||
|
||||
private proxyHandler = {
|
||||
get(target: any, prop: any, receiver: any) {
|
||||
// console.log('get', prop, typeof target[prop]);
|
||||
if (typeof target[prop] === 'undefined') {
|
||||
// 如果方法不存在,返回一个函数,这个函数调用existentMethod
|
||||
return (...args: unknown[]) => {
|
||||
logDebug(`${target.constructor.name} has no method ${prop}`);
|
||||
};
|
||||
}
|
||||
// 如果方法存在,正常返回
|
||||
return Reflect.get(target, prop, receiver);
|
||||
}
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.engine = new QQWrapper.NodeIQQNTWrapperEngine();
|
||||
this.util = new QQWrapper.NodeQQNTWrapperUtil();
|
||||
this.loginService = new QQWrapper.NodeIKernelLoginService();
|
||||
this.session = new QQWrapper.NodeIQQNTWrapperSession();
|
||||
this.loginListener = new LoginListener();
|
||||
this.loginListener.onUserLoggedIn = (userid: string) => {
|
||||
logError('当前账号(' + userid + ')已登录,无法重复登录');
|
||||
};
|
||||
this.initConfig();
|
||||
this.loginListener.onQRCodeLoginSucceed = (arg) => {
|
||||
this.initSession(arg.uin, arg.uid).then((r) => {
|
||||
selfInfo.uin = arg.uin;
|
||||
selfInfo.uid = arg.uid;
|
||||
napCatConfig.read();
|
||||
setLogLevel(napCatConfig.fileLogLevel, napCatConfig.consoleLogLevel);
|
||||
enableFileLog(napCatConfig.fileLog);
|
||||
enableConsoleLog(napCatConfig.consoleLog);
|
||||
setLogSelfInfo(selfInfo);
|
||||
const dataPath = path.resolve(this.dataPath, './NapCat/data');
|
||||
fs.mkdirSync(dataPath, { recursive: true });
|
||||
logDebug('本账号数据/缓存目录:', dataPath);
|
||||
dbUtil.init(path.resolve(dataPath, `./${arg.uin}-v2.db`)).then(() => {
|
||||
this.initDataListener();
|
||||
this.onLoginSuccessFuncList.map(cb => {
|
||||
new Promise((resolve, reject) => {
|
||||
const result = cb(arg.uin, arg.uid);
|
||||
if (result instanceof Promise) {
|
||||
result.then(resolve).catch(reject);
|
||||
}
|
||||
}).then();
|
||||
});
|
||||
}).catch((e) => {
|
||||
logError('数据库初始化失败', e);
|
||||
});
|
||||
// this.initDataListener();
|
||||
}).catch((e) => {
|
||||
logError('initSession failed', e);
|
||||
throw new Error(`启动失败: ${JSON.stringify(e)}`);
|
||||
});
|
||||
};
|
||||
// todo: 登录失败处理
|
||||
this.loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => {
|
||||
logError('登录失败(onQRCodeSessionFailed)', errMsg);
|
||||
if (errType == 1 && errCode == 3) {
|
||||
// 二维码过期刷新
|
||||
this.loginService.getQRCodePicture();
|
||||
}
|
||||
};
|
||||
this.loginListener.onLoginFailed = (args) => {
|
||||
logError('登录失败(onLoginFailed)', args);
|
||||
};
|
||||
|
||||
this.loginListener = new Proxy(this.loginListener, this.proxyHandler);
|
||||
// 初始化流程:initConfig, login, initSession, loginSuccess | initDataListener
|
||||
this.loginService.addKernelLoginListener(new QQWrapper.NodeIKernelLoginListener(this.loginListener));
|
||||
}
|
||||
|
||||
get dataPath(): string {
|
||||
let result = this.util.getNTUserDataInfoConfig();
|
||||
if (!result) {
|
||||
result = path.resolve(os.homedir(), './.config/QQ');
|
||||
fs.mkdirSync(result, { recursive: true });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
get dataPathGlobal(): string {
|
||||
return path.resolve(this.dataPath, './nt_qq/global');
|
||||
}
|
||||
|
||||
private initConfig() {
|
||||
this.engine.initWithDeskTopConfig({
|
||||
base_path_prefix: '',
|
||||
platform_type: 3,
|
||||
app_type: 4,
|
||||
app_version: qqVersionConfigInfo.curVersion,
|
||||
os_version: 'Windows 10 Pro',
|
||||
use_xlog: true,
|
||||
qua: `V1_WIN_NQ_${qqVersionConfigInfo.curVersion.replace('-', '_')}_GW_B`,
|
||||
global_path_config: {
|
||||
desktopGlobalPath: this.dataPathGlobal,
|
||||
},
|
||||
thumb_config: { maxSide: 324, minSide: 48, longLimit: 6, density: 2 }
|
||||
}, new QQWrapper.NodeIGlobalAdapter(new GlobalAdapter()));
|
||||
this.loginService.initConfig({
|
||||
machineId: '',
|
||||
appid,
|
||||
platVer: systemVersion,
|
||||
commonPath: this.dataPathGlobal,
|
||||
clientVer: qqVersionConfigInfo.curVersion,
|
||||
hostName: hostname
|
||||
});
|
||||
}
|
||||
|
||||
private initSession(uin: string, uid: string): Promise<number> {
|
||||
return new Promise(async (res, rej) => {
|
||||
|
||||
const sessionConfig = await genSessionConfig(uin, uid, this.dataPath);
|
||||
const sessionListener = new SessionListener();
|
||||
sessionListener.onSessionInitComplete = (r: unknown) => {
|
||||
if ((r as number) === 0) {
|
||||
return res(0);
|
||||
}
|
||||
rej(r);
|
||||
};
|
||||
// const oldOnSendOidbRepl = this.session.onSendOidbRepl;
|
||||
// this.session.onSendOidbRepl = (...args: unknown[]) => {
|
||||
// console.log('onSendOidbRepl', args);
|
||||
// return oldOnSendOidbRepl(...args);
|
||||
// };
|
||||
this.session.init(sessionConfig,
|
||||
new QQWrapper.NodeIDependsAdapter(new DependsAdapter()),
|
||||
new QQWrapper.NodeIDispatcherAdapter(new DispatcherAdapter()),
|
||||
new QQWrapper.NodeIKernelSessionListener(sessionListener)
|
||||
);
|
||||
try {
|
||||
this.session.startNT(0);
|
||||
} catch (__) { /* Empty */
|
||||
try {
|
||||
this.session.startNT();
|
||||
} catch (e) {
|
||||
rej('init failed ' + e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private initDataListener() {
|
||||
// 消息相关
|
||||
interface LineDevice {
|
||||
instanceId: number
|
||||
clientType: number
|
||||
devUid: string
|
||||
}
|
||||
interface KickedOffLineInfo {
|
||||
appId: number
|
||||
instanceId: number
|
||||
sameDevice: boolean
|
||||
tipsDesc: string
|
||||
tipsTitle: string
|
||||
kickedType: number
|
||||
securityKickedType: number
|
||||
}
|
||||
const msgListener = new MsgListener();
|
||||
msgListener.onLineDev = (Devices: LineDevice[]) => {
|
||||
Devices.map((Device: LineDevice) => {
|
||||
if (Device.clientType === 2) {
|
||||
log('账号设备(' + Device.devUid + ') 在线状态变更');
|
||||
}
|
||||
});
|
||||
};
|
||||
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
|
||||
// 下线通知
|
||||
log('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
|
||||
};
|
||||
// msgListener.onMsgInfoListUpdate = (msgInfoList: RawMessage[]) => {
|
||||
// stat.packet_received += 1;
|
||||
// msgInfoList.map(msg => {
|
||||
// console.log("onMsgInfoListUpdate", msg);
|
||||
// if (msg.recallTime === '0') { // 不是撤回消息才入库/更新
|
||||
// dbUtil.addMsg(msg).then().catch();
|
||||
// }
|
||||
// else {
|
||||
// // 撤回的消息
|
||||
// dbUtil.getMsgByLongId(msg.msgId).then(existMsg => {
|
||||
// if (existMsg) {
|
||||
// existMsg.recallTime = msg.recallTime;
|
||||
// dbUtil.updateMsg(existMsg).then();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
msgListener.onAddSendMsg = (msg: RawMessage) => {
|
||||
stat.packet_sent += 1;
|
||||
stat.message_sent += 1;
|
||||
stat.last_message_time = Math.floor(Date.now() / 1000);
|
||||
};
|
||||
msgListener.onRecvMsg = (msgList: RawMessage[]) => {
|
||||
stat.packet_received += 1;
|
||||
stat.message_received += msgList.length;
|
||||
stat.last_message_time = Math.floor(Date.now() / 1000);
|
||||
};
|
||||
msgListener.onRecvSysMsg = (...args) => {
|
||||
stat.packet_received += 1;
|
||||
};
|
||||
this.addListener(msgListener);
|
||||
// 好友相关
|
||||
const buddyListener = new BuddyListener();
|
||||
buddyListener.onBuddyListChange = arg => {
|
||||
rawFriends.length = 0;
|
||||
rawFriends.push(...arg);
|
||||
// console.log('onBuddyListChange', arg);
|
||||
for (const categoryItem of arg) {
|
||||
for (const friend of categoryItem.buddyList) {
|
||||
// console.log("onBuddyListChange", friend)
|
||||
const existFriend = friends.get(friend.uid);
|
||||
if (existFriend) {
|
||||
Object.assign(existFriend, friend);
|
||||
}
|
||||
else {
|
||||
friends.set(friend.uid, friend);
|
||||
}
|
||||
}
|
||||
// console.log("onBuddyListChange", friend)
|
||||
}
|
||||
};
|
||||
this.addListener(buddyListener);
|
||||
// 刷新一次好友列表
|
||||
this.session.getBuddyService().getBuddyList(true).then(arg => {
|
||||
// console.log('getBuddyList', arg);
|
||||
});
|
||||
interface SelfStatusInfo {
|
||||
uid: string
|
||||
status: number
|
||||
extStatus: number
|
||||
termType: number
|
||||
netType: number
|
||||
iconType: number
|
||||
customStatus: any
|
||||
setTime: string
|
||||
}
|
||||
const profileListener = new ProfileListener();
|
||||
profileListener.onProfileDetailInfoChanged = (profile) => {
|
||||
if (profile.uid === selfInfo.uid) {
|
||||
Object.assign(selfInfo, profile);
|
||||
}
|
||||
};
|
||||
profileListener.onSelfStatusChanged = (Info: SelfStatusInfo) => {
|
||||
// if (Info.status == 20) {
|
||||
// log("账号状态变更为离线")
|
||||
// }
|
||||
};
|
||||
this.addListener(profileListener);
|
||||
|
||||
// 群相关
|
||||
const groupListener = new GroupListener();
|
||||
groupListener.onGroupListUpdate = (updateType, groupList) => {
|
||||
// console.log("onGroupListUpdate", updateType, groupList)
|
||||
groupList.map(g => {
|
||||
const existGroup = groups.get(g.groupCode);
|
||||
//群成员数量变化 应该刷新缓存
|
||||
if (existGroup && g.memberCount === existGroup.memberCount) {
|
||||
Object.assign(existGroup, g);
|
||||
}
|
||||
else {
|
||||
groups.set(g.groupCode, g);
|
||||
// 获取群成员
|
||||
}
|
||||
const sceneId = this.session.getGroupService().createMemberListScene(g.groupCode, 'groupMemberList_MainWindow');
|
||||
this.session.getGroupService().getNextMemberList(sceneId!, undefined, 3000).then(r => {
|
||||
// console.log(`get group ${g.groupCode} members`, r);
|
||||
// r.result.infos.forEach(member => {
|
||||
// });
|
||||
// groupMembers.set(g.groupCode, r.result.infos);
|
||||
});
|
||||
});
|
||||
};
|
||||
groupListener.onMemberListChange = (arg) => {
|
||||
// todo: 应该加一个内部自己维护的成员变动callback,用于判断成员变化通知
|
||||
const groupCode = arg.sceneId.split('_')[0];
|
||||
if (groupMembers.has(groupCode)) {
|
||||
const existMembers = groupMembers.get(groupCode)!;
|
||||
arg.infos.forEach((member, uid) => {
|
||||
const existMember = existMembers.get(uid);
|
||||
if (existMember) {
|
||||
Object.assign(existMember, member);
|
||||
}
|
||||
else {
|
||||
existMembers!.set(uid, member);
|
||||
}
|
||||
//移除成员
|
||||
if (member.isDelete) {
|
||||
existMembers.delete(uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
groupMembers.set(groupCode, arg.infos);
|
||||
}
|
||||
// console.log('onMemberListChange', groupCode, arg);
|
||||
};
|
||||
groupListener.onMemberInfoChange = (groupCode, changeType, members) => {
|
||||
// console.log('onMemberInfoChange', arg);
|
||||
if (changeType === 0 && members.get(selfInfo.uid)?.isDelete) {
|
||||
// 自身退群或者被踢退群 5s用于Api操作 之后不再出现
|
||||
setTimeout(() => {
|
||||
groups.delete(groupCode);
|
||||
}, 5000);
|
||||
|
||||
}
|
||||
const existMembers = groupMembers.get(groupCode);
|
||||
if (existMembers) {
|
||||
members.forEach((member, uid) => {
|
||||
const existMember = existMembers.get(uid);
|
||||
if (existMember) {
|
||||
Object.assign(existMember, member);
|
||||
}
|
||||
else {
|
||||
existMembers.set(uid, member);
|
||||
}
|
||||
//移除成员
|
||||
if (member.isDelete) {
|
||||
existMembers.delete(uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
groupMembers.set(groupCode, members);
|
||||
}
|
||||
};
|
||||
this.addListener(groupListener);
|
||||
}
|
||||
|
||||
addListener(
|
||||
listener: BuddyListener | GroupListener | MsgListener | ProfileListener
|
||||
): number {
|
||||
// 根据listener的类型,找到对应的service,然后调用addListener方法
|
||||
// logDebug('addListener', listener.constructor.name);
|
||||
|
||||
// proxy listener,调用 listener 不存在的方法时不会报错
|
||||
|
||||
listener = new Proxy(listener, this.proxyHandler);
|
||||
switch (listener.constructor.name) {
|
||||
case 'BuddyListener': {
|
||||
return this.session.getBuddyService().addKernelBuddyListener(new QQWrapper.NodeIKernelBuddyListener(listener as BuddyListener));
|
||||
}
|
||||
case 'GroupListener': {
|
||||
return this.session.getGroupService().addKernelGroupListener(new QQWrapper.NodeIKernelGroupListener(listener as GroupListener));
|
||||
}
|
||||
case 'MsgListener': {
|
||||
return this.session.getMsgService().addKernelMsgListener(new QQWrapper.NodeIKernelMsgListener(listener as MsgListener));
|
||||
}
|
||||
case 'ProfileListener': {
|
||||
return this.session.getProfileService().addKernelProfileListener(new QQWrapper.NodeIKernelProfileListener(listener as ProfileListener));
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
onLoginSuccess(func: OnLoginSuccess) {
|
||||
NTEventDispatch.init({
|
||||
ListenerMap: QQWrapper,
|
||||
WrapperSession: this.session,
|
||||
});
|
||||
this.onLoginSuccessFuncList.push(func);
|
||||
}
|
||||
|
||||
async quickLogin(uin: string): Promise<QuickLoginResult> {
|
||||
const loginList = await this.loginService.getLoginList();
|
||||
|
||||
if (loginList.result !== 0) throw new Error('没有可快速登录的QQ号');
|
||||
const currentLogin = loginList.LocalLoginInfoList.find((item) => item.uin === uin);
|
||||
if (!currentLogin || !currentLogin?.isQuickLogin) throw new Error(`${uin}快速登录不可用`);
|
||||
|
||||
await sleep(1000);
|
||||
const loginRet = await this.loginService.quickLoginWithUin(uin);
|
||||
if (!loginRet.result) {
|
||||
throw new Error('快速登录失败 ' + loginRet.loginErrorInfo.errMsg);
|
||||
}
|
||||
return loginRet;
|
||||
}
|
||||
|
||||
async qrLogin(cb: (url: string, base64: string, buffer: Buffer) => Promise<void>) {
|
||||
return new Promise<{ url: string, base64: string, buffer: Buffer }>((resolve, reject) => {
|
||||
this.loginListener.onQRCodeGetPicture = (arg) => {
|
||||
const base64Data = arg.pngBase64QrcodeData.split('data:image/png;base64,')[1];
|
||||
const buffer = Buffer.from(base64Data, 'base64');
|
||||
cb(arg.qrcodeUrl, arg.pngBase64QrcodeData, buffer);
|
||||
};
|
||||
this.loginService.getQRCodePicture();
|
||||
});
|
||||
}
|
||||
|
||||
async passwordLogin(uin: string, password: string, proofSig?: string, proofRand?: string, proofSid?: string) {
|
||||
const passwordMd5 = crypto.createHash('md5').update(password).digest('hex');
|
||||
const loginArg: passwordLoginArgType = {
|
||||
uin,
|
||||
passwordMd5,
|
||||
step: proofSig && proofRand && proofSid ? 1 : 0,
|
||||
newDeviceLoginSig: '',
|
||||
proofWaterSig: proofSig || '',
|
||||
proofWaterRand: proofRand || '',
|
||||
proofWaterSid: proofSid || ''
|
||||
};
|
||||
|
||||
await this.loginService.getLoginList();
|
||||
await sleep(1000);
|
||||
|
||||
const ret = await this.loginService.passwordLogin(loginArg);
|
||||
|
||||
switch (ret.result) {
|
||||
case '0': { // Success
|
||||
break;
|
||||
}
|
||||
case '140022008': { // CAPTCHA required
|
||||
break;
|
||||
}
|
||||
case '4': // Mobile verify required
|
||||
case '140022013': // Incorrect password
|
||||
default:
|
||||
}
|
||||
}
|
||||
async getQuickLoginList() {
|
||||
const loginList = await this.loginService.getLoginList();
|
||||
return loginList;
|
||||
}
|
||||
}
|
||||
|
||||
export const napCatCore = new NapCatCore();
|
||||
|
||||
|
||||
97
src/core/src/data.ts
Normal file
97
src/core/src/data.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import {
|
||||
type Friend,
|
||||
type Group,
|
||||
type GroupMember, GroupNotify,
|
||||
type SelfInfo,
|
||||
BuddyCategoryType
|
||||
} from './entities';
|
||||
import { isNumeric } from '@/common/utils/helper';
|
||||
import { NTQQGroupApi } from '@/core/apis';
|
||||
|
||||
export const selfInfo: SelfInfo = {
|
||||
uid: '',
|
||||
uin: '',
|
||||
nick: '',
|
||||
online: true
|
||||
};
|
||||
// 未来只在此处保留 selfInfo stat
|
||||
// groupCode -> Group
|
||||
export const groups: Map<string, Group> = new Map<string, Group>();
|
||||
|
||||
export function deleteGroup(groupQQ: string) {
|
||||
groups.delete(groupQQ);
|
||||
groupMembers.delete(groupQQ);
|
||||
}
|
||||
|
||||
// 群号 -> 群成员map(uid=>GroupMember)
|
||||
export const groupMembers: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
|
||||
|
||||
// uid -> Friend 下面这俩个准备移除 QQ里面自带缓存
|
||||
export const friends: Map<string, Friend> = new Map<string, Friend>();
|
||||
export const rawFriends: Array<BuddyCategoryType> = []; // 带分组的好友列表
|
||||
|
||||
export const groupNotifies: Record<string, GroupNotify> = {}; // flag->GroupNotify
|
||||
export async function getGroup(qq: string | number): Promise<Group | undefined> {
|
||||
let group = groups.get(qq.toString());
|
||||
if (!group) {
|
||||
try {
|
||||
const _groups = await NTQQGroupApi.getGroups();
|
||||
if (_groups.length) {
|
||||
_groups.forEach(g => {
|
||||
groups.set(g.groupCode, g);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
group = groups.get(qq.toString());
|
||||
return group;
|
||||
}
|
||||
|
||||
export async function getGroupMember(groupQQ: string | number, memberUinOrUid: string | number) {
|
||||
groupQQ = groupQQ.toString();
|
||||
memberUinOrUid = memberUinOrUid.toString();
|
||||
let members = groupMembers.get(groupQQ);
|
||||
if (!members) {
|
||||
try {
|
||||
members = await NTQQGroupApi.getGroupMembers(groupQQ);
|
||||
// 更新群成员列表
|
||||
groupMembers.set(groupQQ, members);
|
||||
}
|
||||
catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// log('getGroupMember', members);
|
||||
const getMember = () => {
|
||||
let member: GroupMember | undefined = undefined;
|
||||
if (isNumeric(memberUinOrUid)) {
|
||||
member = Array.from(members!.values()).find(member => member.uin === memberUinOrUid);
|
||||
} else {
|
||||
member = members!.get(memberUinOrUid);
|
||||
}
|
||||
return member;
|
||||
};
|
||||
let member = getMember();
|
||||
if (!member) {
|
||||
members = await NTQQGroupApi.getGroupMembers(groupQQ);
|
||||
member = getMember();
|
||||
}
|
||||
return member;
|
||||
}
|
||||
// 考虑优化 移入QQ缓存或使用Api直接获取
|
||||
export const tempGroupCodeMap: Record<string, string> = {}; // peerUid => 群号
|
||||
|
||||
// 保留 需要频繁读写
|
||||
export const stat = {
|
||||
packet_received: 0,
|
||||
packet_sent: 0,
|
||||
message_received: 0,
|
||||
message_sent: 0,
|
||||
last_message_time: 0,
|
||||
// 以下字段无用, 全部为0
|
||||
disconnect_times: 0,
|
||||
lost_times: 0,
|
||||
packet_lost: 0,
|
||||
};
|
||||
65
src/core/src/entities/cache.ts
Normal file
65
src/core/src/entities/cache.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { ChatType } from './msg';
|
||||
|
||||
export interface CacheScanResult {
|
||||
result: number;
|
||||
size: [ // 单位为字节
|
||||
string, // 系统总存储空间
|
||||
string, // 系统可用存储空间
|
||||
string, // 系统已用存储空间
|
||||
string, // QQ总大小
|
||||
string, // 「聊天与文件」大小
|
||||
string, // 未知
|
||||
string, // 「缓存数据」大小
|
||||
string, // 「其他数据」大小
|
||||
string, // 未知
|
||||
]
|
||||
}
|
||||
|
||||
export interface ChatCacheList {
|
||||
pageCount: number;
|
||||
infos: ChatCacheListItem[]
|
||||
};
|
||||
|
||||
export interface ChatCacheListItem {
|
||||
chatType: ChatType;
|
||||
basicChatCacheInfo: ChatCacheListItemBasic;
|
||||
guildChatCacheInfo: unknown[]; // TODO: 没用过频道所以不知道这里边的详细内容
|
||||
}
|
||||
|
||||
export interface ChatCacheListItemBasic {
|
||||
chatSize: string;
|
||||
chatTime: string;
|
||||
uid: string;
|
||||
uin: string;
|
||||
remarkName: string;
|
||||
nickName: string;
|
||||
chatType?: ChatType;
|
||||
isChecked?: boolean;
|
||||
}
|
||||
|
||||
export enum CacheFileType {
|
||||
IMAGE = 0,
|
||||
VIDEO = 1,
|
||||
AUDIO = 2,
|
||||
DOCUMENT = 3,
|
||||
OTHER = 4,
|
||||
}
|
||||
|
||||
export interface CacheFileList {
|
||||
infos: CacheFileListItem[],
|
||||
}
|
||||
|
||||
export interface CacheFileListItem {
|
||||
fileSize: string;
|
||||
fileTime: string;
|
||||
fileKey: string;
|
||||
elementId: string;
|
||||
elementIdStr: string;
|
||||
fileType: CacheFileType;
|
||||
path: string;
|
||||
fileName: string;
|
||||
senderId: string;
|
||||
previewPath: string;
|
||||
senderName: string;
|
||||
isChecked?: boolean;
|
||||
}
|
||||
370
src/core/src/entities/constructor.ts
Normal file
370
src/core/src/entities/constructor.ts
Normal file
@@ -0,0 +1,370 @@
|
||||
import {
|
||||
AtType,
|
||||
ElementType, FaceIndex, FaceType, PicElement,
|
||||
PicType,
|
||||
SendArkElement,
|
||||
SendFaceElement,
|
||||
SendFileElement, SendMarkdownElement, SendMarketFaceElement,
|
||||
SendPicElement,
|
||||
SendPttElement,
|
||||
SendReplyElement,
|
||||
SendTextElement,
|
||||
SendVideoElement
|
||||
} from './index';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import ffmpeg from 'fluent-ffmpeg';
|
||||
import { NTQQFileApi } from '@/core/apis/file';
|
||||
import { calculateFileMD5, isGIF } from '@/common/utils/file';
|
||||
import { log, logDebug, logError } from '@/common/utils/log';
|
||||
import { defaultVideoThumb, getVideoInfo } from '@/common/utils/video';
|
||||
import { encodeSilk } from '@/common/utils/audio';
|
||||
import { isNull } from '@/common/utils/helper';
|
||||
import faceConfig from './face_config.json';
|
||||
import * as pathLib from 'node:path';
|
||||
import { SignMiniApp } from '../apis';
|
||||
|
||||
export const mFaceCache = new Map<string, string>(); // emojiId -> faceName
|
||||
|
||||
|
||||
export class SendMsgElementConstructor {
|
||||
static text(content: string): SendTextElement {
|
||||
return {
|
||||
elementType: ElementType.TEXT,
|
||||
elementId: '',
|
||||
textElement: {
|
||||
content,
|
||||
atType: AtType.notAt,
|
||||
atUid: '',
|
||||
atTinyId: '',
|
||||
atNtUid: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static at(atUid: string, atNtUid: string, atType: AtType, atName: string): SendTextElement {
|
||||
return {
|
||||
elementType: ElementType.TEXT,
|
||||
elementId: '',
|
||||
textElement: {
|
||||
content: `@${atName}`,
|
||||
atType,
|
||||
atUid,
|
||||
atTinyId: '',
|
||||
atNtUid,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static reply(msgSeq: string, msgId: string, senderUin: string, senderUinStr: string): SendReplyElement {
|
||||
return {
|
||||
elementType: ElementType.REPLY,
|
||||
elementId: '',
|
||||
replyElement: {
|
||||
replayMsgSeq: msgSeq, // raw.msgSeq
|
||||
replayMsgId: msgId, // raw.msgId
|
||||
senderUin: senderUin,
|
||||
senderUinStr: senderUinStr,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static async pic(picPath: string, summary: string = '', subType: 0 | 1 = 0): Promise<SendPicElement> {
|
||||
const { md5, fileName, path, fileSize } = await NTQQFileApi.uploadFile(picPath, ElementType.PIC, subType);
|
||||
if (fileSize === 0) {
|
||||
throw '文件异常,大小为0';
|
||||
}
|
||||
const imageSize = await NTQQFileApi.getImageSize(picPath);
|
||||
const picElement: any = {
|
||||
md5HexStr: md5,
|
||||
fileSize: fileSize.toString(),
|
||||
picWidth: imageSize?.width,
|
||||
picHeight: imageSize?.height,
|
||||
fileName: fileName,
|
||||
sourcePath: path,
|
||||
original: true,
|
||||
picType: isGIF(picPath) ? PicType.gif : PicType.jpg,
|
||||
picSubType: subType,
|
||||
fileUuid: '',
|
||||
fileSubId: '',
|
||||
thumbFileSize: 0,
|
||||
summary
|
||||
};
|
||||
//logDebug('图片信息', picElement);
|
||||
return {
|
||||
elementType: ElementType.PIC,
|
||||
elementId: '',
|
||||
picElement,
|
||||
};
|
||||
}
|
||||
|
||||
static async file(filePath: string, fileName: string = '', folderId: string = ''): Promise<SendFileElement> {
|
||||
const { md5, fileName: _fileName, path, fileSize } = await NTQQFileApi.uploadFile(filePath, ElementType.FILE);
|
||||
if (fileSize === 0) {
|
||||
throw '文件异常,大小为0';
|
||||
}
|
||||
const element: SendFileElement = {
|
||||
elementType: ElementType.FILE,
|
||||
elementId: '',
|
||||
fileElement: {
|
||||
fileName: fileName || _fileName,
|
||||
folderId: folderId,
|
||||
'filePath': path!,
|
||||
'fileSize': (fileSize).toString(),
|
||||
}
|
||||
};
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
static async video(filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
|
||||
const { fileName: _fileName, path, fileSize, md5 } = await NTQQFileApi.uploadFile(filePath, ElementType.VIDEO);
|
||||
if (fileSize === 0) {
|
||||
throw '文件异常,大小为0';
|
||||
}
|
||||
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
|
||||
thumb = pathLib.dirname(thumb);
|
||||
// log("thumb 目录", thumb)
|
||||
let videoInfo = {
|
||||
width: 1920, height: 1080,
|
||||
time: 15,
|
||||
format: 'mp4',
|
||||
size: fileSize,
|
||||
filePath
|
||||
};
|
||||
try {
|
||||
videoInfo = await getVideoInfo(path);
|
||||
//logDebug('视频信息', videoInfo);
|
||||
} catch (e) {
|
||||
logError('获取视频信息失败', e);
|
||||
}
|
||||
const createThumb = new Promise<string>((resolve, reject) => {
|
||||
const thumbFileName = `${md5}_0.png`;
|
||||
const thumbPath = pathLib.join(thumb, thumbFileName);
|
||||
ffmpeg(filePath)
|
||||
.on('end', () => {
|
||||
})
|
||||
.on('error', (err) => {
|
||||
logDebug('获取视频封面失败,使用默认封面', err);
|
||||
if (diyThumbPath) {
|
||||
fs.copyFile(diyThumbPath, thumbPath).then(() => {
|
||||
resolve(thumbPath);
|
||||
}).catch(reject);
|
||||
} else {
|
||||
fs.writeFile(thumbPath, defaultVideoThumb).then(() => {
|
||||
resolve(thumbPath);
|
||||
}).catch(reject);
|
||||
}
|
||||
})
|
||||
.screenshots({
|
||||
timestamps: [0],
|
||||
filename: thumbFileName,
|
||||
folder: thumb,
|
||||
size: videoInfo.width + 'x' + videoInfo.height
|
||||
}).on('end', () => {
|
||||
resolve(thumbPath);
|
||||
});
|
||||
});
|
||||
const thumbPath = new Map();
|
||||
const _thumbPath = await createThumb;
|
||||
const thumbSize = (await fs.stat(_thumbPath)).size;
|
||||
// log("生成缩略图", _thumbPath)
|
||||
thumbPath.set(0, _thumbPath);
|
||||
const thumbMd5 = await calculateFileMD5(_thumbPath);
|
||||
const element: SendVideoElement = {
|
||||
elementType: ElementType.VIDEO,
|
||||
elementId: '',
|
||||
videoElement: {
|
||||
fileName: fileName || _fileName,
|
||||
filePath: path,
|
||||
videoMd5: md5,
|
||||
thumbMd5,
|
||||
fileTime: videoInfo.time,
|
||||
thumbPath: thumbPath,
|
||||
thumbSize,
|
||||
thumbWidth: videoInfo.width,
|
||||
thumbHeight: videoInfo.height,
|
||||
fileSize: '' + fileSize,
|
||||
// fileUuid: "",
|
||||
// transferStatus: 0,
|
||||
// progress: 0,
|
||||
// invalidState: 0,
|
||||
// fileSubId: "",
|
||||
// fileBizId: null,
|
||||
// originVideoMd5: "",
|
||||
// fileFormat: 2,
|
||||
// import_rich_media_context: null,
|
||||
// sourceVideoCodecFormat: 2
|
||||
}
|
||||
};
|
||||
return element;
|
||||
}
|
||||
|
||||
static async ptt(pttPath: string): Promise<SendPttElement> {
|
||||
const { converted, path: silkPath, duration } = await encodeSilk(pttPath);
|
||||
// log("生成语音", silkPath, duration);
|
||||
if (!silkPath) {
|
||||
throw '语音转换失败, 请检查语音文件是否正常';
|
||||
}
|
||||
const { md5, fileName, path, fileSize } = await NTQQFileApi.uploadFile(silkPath!, ElementType.PTT);
|
||||
if (fileSize === 0) {
|
||||
throw '文件异常,大小为0';
|
||||
}
|
||||
if (converted) {
|
||||
fs.unlink(silkPath).then();
|
||||
}
|
||||
return {
|
||||
elementType: ElementType.PTT,
|
||||
elementId: '',
|
||||
pttElement: {
|
||||
fileName: fileName,
|
||||
filePath: path,
|
||||
md5HexStr: md5,
|
||||
fileSize: fileSize,
|
||||
// duration: Math.max(1, Math.round(fileSize / 1024 / 3)), // 一秒钟大概是3kb大小, 小于1秒的按1秒算
|
||||
duration: duration || 1,
|
||||
formatType: 1,
|
||||
voiceType: 1,
|
||||
voiceChangeType: 0,
|
||||
canConvert2Text: true,
|
||||
waveAmplitudes: [
|
||||
0, 18, 9, 23, 16, 17, 16, 15, 44, 17, 24, 20, 14, 15, 17,
|
||||
],
|
||||
fileSubId: '',
|
||||
playState: 1,
|
||||
autoConvertText: 0,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static face(faceId: number): SendFaceElement {
|
||||
// 从face_config.json中获取表情名称
|
||||
const sysFaces = faceConfig.sysface;
|
||||
const emojiFaces = faceConfig.emoji;
|
||||
const face: any = sysFaces.find((face) => face.QSid === faceId.toString());
|
||||
faceId = parseInt(faceId.toString());
|
||||
// let faceType = parseInt(faceId.toString().substring(0, 1));
|
||||
let faceType = 1;
|
||||
if (faceId >= 222) {
|
||||
faceType = 2;
|
||||
}
|
||||
if (face.AniStickerType) {
|
||||
faceType = 3;
|
||||
}
|
||||
return {
|
||||
elementType: ElementType.FACE,
|
||||
elementId: '',
|
||||
faceElement: {
|
||||
faceIndex: faceId,
|
||||
faceType,
|
||||
faceText: face.QDes,
|
||||
stickerId: face.AniStickerId,
|
||||
stickerType: face.AniStickerType,
|
||||
packId: face.AniStickerPackId,
|
||||
sourceType: 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static mface(emojiPackageId: number, emojiId: string, key: string, faceName: string): SendMarketFaceElement {
|
||||
return {
|
||||
elementType: ElementType.MFACE,
|
||||
marketFaceElement: {
|
||||
emojiPackageId,
|
||||
emojiId,
|
||||
key,
|
||||
faceName: faceName || mFaceCache.get(emojiId) || '[商城表情]',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static dice(resultId: number | null): SendFaceElement {
|
||||
// 实际测试并不能控制结果
|
||||
|
||||
// 随机1到6
|
||||
// if (isNull(resultId)) resultId = Math.floor(Math.random() * 6) + 1;
|
||||
return {
|
||||
elementType: ElementType.FACE,
|
||||
elementId: '',
|
||||
faceElement: {
|
||||
faceIndex: FaceIndex.dice,
|
||||
faceType: FaceType.dice,
|
||||
'faceText': '[骰子]',
|
||||
'packId': '1',
|
||||
'stickerId': '33',
|
||||
'sourceType': 1,
|
||||
'stickerType': 2,
|
||||
// resultId: resultId.toString(),
|
||||
'surpriseId': '',
|
||||
// "randomType": 1,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 猜拳(石头剪刀布)表情
|
||||
static rps(resultId: number | null): SendFaceElement {
|
||||
// 实际测试并不能控制结果
|
||||
// if (isNull(resultId)) resultId = Math.floor(Math.random() * 3) + 1;
|
||||
return {
|
||||
elementType: ElementType.FACE,
|
||||
elementId: '',
|
||||
faceElement: {
|
||||
'faceIndex': FaceIndex.RPS,
|
||||
'faceText': '[包剪锤]',
|
||||
'faceType': 3,
|
||||
'packId': '1',
|
||||
'stickerId': '34',
|
||||
'sourceType': 1,
|
||||
'stickerType': 2,
|
||||
// 'resultId': resultId.toString(),
|
||||
'surpriseId': '',
|
||||
// "randomType": 1,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static ark(data: any): SendArkElement {
|
||||
if (typeof data !== 'string') {
|
||||
data = JSON.stringify(data);
|
||||
}
|
||||
return {
|
||||
elementType: ElementType.ARK,
|
||||
elementId: '',
|
||||
arkElement: {
|
||||
bytesData: data,
|
||||
linkInfo: null,
|
||||
subElementType: null
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static markdown(content: string): SendMarkdownElement {
|
||||
return {
|
||||
elementType: ElementType.MARKDOWN,
|
||||
elementId: '',
|
||||
markdownElement: {
|
||||
content
|
||||
}
|
||||
};
|
||||
}
|
||||
static async miniapp(): Promise<SendArkElement> {
|
||||
let ret = await SignMiniApp({
|
||||
prompt: "Bot Test",
|
||||
title: "Bot Test",
|
||||
preview: "https://tianquan.gtimg.cn/qqAIAgent/item/7/square.png",
|
||||
jumpUrl: "https://www.bilibili.com/",
|
||||
tag: "Bot Test",
|
||||
tagIcon: "https://tianquan.gtimg.cn/shoal/qqAIAgent/3e9d70c9-d98c-45b8-80b4-79d82971b514.png",
|
||||
source: "Bot Test",
|
||||
sourcelogo: "https://tianquan.gtimg.cn/shoal/qqAIAgent/3e9d70c9-d98c-45b8-80b4-79d82971b514.png"
|
||||
});
|
||||
return {
|
||||
elementType: ElementType.ARK,
|
||||
elementId: '',
|
||||
arkElement: {
|
||||
bytesData: ret,
|
||||
linkInfo: null,
|
||||
subElementType: null
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
3665
src/core/src/entities/face_config.json
Normal file
3665
src/core/src/entities/face_config.json
Normal file
File diff suppressed because it is too large
Load Diff
55
src/core/src/entities/group.ts
Normal file
55
src/core/src/entities/group.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { QQLevel, Sex } from './user';
|
||||
|
||||
export interface Group {
|
||||
groupCode: string,
|
||||
maxMember: number,
|
||||
memberCount: number,
|
||||
groupName: string,
|
||||
groupStatus: 0,
|
||||
memberRole: 2,
|
||||
isTop: boolean,
|
||||
toppedTimestamp: string,
|
||||
privilegeFlag: number, //65760
|
||||
isConf: boolean,
|
||||
hasModifyConfGroupFace: boolean,
|
||||
hasModifyConfGroupName: boolean,
|
||||
remarkName: string,
|
||||
hasMemo: boolean,
|
||||
groupShutupExpireTime: string, //"0",
|
||||
personShutupExpireTime: string, //"0",
|
||||
discussToGroupUin: string, //"0",
|
||||
discussToGroupMaxMsgSeq: number,
|
||||
discussToGroupTime: number,
|
||||
groupFlagExt: number, //1073938496,
|
||||
authGroupType: number, //0,
|
||||
groupCreditLevel: number, //0,
|
||||
groupFlagExt3: number, //0,
|
||||
groupOwnerId: {
|
||||
memberUin: string, //"0",
|
||||
memberUid: string, //"u_fbf8N7aeuZEnUiJAbQ9R8Q"
|
||||
}
|
||||
}
|
||||
|
||||
export enum GroupMemberRole {
|
||||
normal = 2,
|
||||
admin = 3,
|
||||
owner = 4
|
||||
}
|
||||
|
||||
export interface GroupMember {
|
||||
memberSpecialTitle?: string;
|
||||
avatarPath: string;
|
||||
cardName: string;
|
||||
cardType: number;
|
||||
isDelete: boolean;
|
||||
nick: string;
|
||||
qid: string;
|
||||
remark: string;
|
||||
role: GroupMemberRole; // 群主:4, 管理员:3,群员:2
|
||||
shutUpTime: number; // 禁言时间,单位是什么暂时不清楚
|
||||
uid: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
isRobot: boolean;
|
||||
sex?: Sex
|
||||
qqLevel?: QQLevel
|
||||
}
|
||||
7
src/core/src/entities/index.ts
Normal file
7
src/core/src/entities/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export * from './user';
|
||||
export * from './group';
|
||||
export * from './msg';
|
||||
export * from './notify';
|
||||
export * from './cache';
|
||||
export * from './constructor';
|
||||
|
||||
540
src/core/src/entities/msg.ts
Normal file
540
src/core/src/entities/msg.ts
Normal file
@@ -0,0 +1,540 @@
|
||||
import { GroupMemberRole } from './group';
|
||||
|
||||
|
||||
export interface Peer {
|
||||
chatType: ChatType;
|
||||
peerUid: string; // 如果是群聊uid为群号,私聊uid就是加密的字符串
|
||||
guildId?: string;
|
||||
}
|
||||
export interface KickedOffLineInfo {
|
||||
appId: number
|
||||
instanceId: number
|
||||
sameDevice: boolean
|
||||
tipsDesc: string
|
||||
tipsTitle: string
|
||||
kickedType: number
|
||||
securityKickedType: number
|
||||
}
|
||||
export interface GetFileListParam {
|
||||
sortType: number
|
||||
fileCount: number
|
||||
startIndex: number
|
||||
sortOrder: number
|
||||
showOnlinedocFolder: number
|
||||
}
|
||||
export enum ElementType {
|
||||
TEXT = 1,
|
||||
PIC = 2,
|
||||
FILE = 3,
|
||||
PTT = 4,
|
||||
VIDEO = 5,
|
||||
FACE = 6,
|
||||
REPLY = 7,
|
||||
ARK = 10,
|
||||
MFACE = 11,
|
||||
MARKDOWN = 14
|
||||
}
|
||||
|
||||
export interface SendTextElement {
|
||||
elementType: ElementType.TEXT;
|
||||
elementId: string;
|
||||
textElement: {
|
||||
content: string;
|
||||
atType: number;
|
||||
atUid: string;
|
||||
atTinyId: string;
|
||||
atNtUid: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SendPttElement {
|
||||
elementType: ElementType.PTT;
|
||||
elementId: string;
|
||||
pttElement: {
|
||||
fileName: string;
|
||||
filePath: string;
|
||||
md5HexStr: string;
|
||||
fileSize: number;
|
||||
duration: number; // 单位是秒
|
||||
formatType: number;
|
||||
voiceType: number;
|
||||
voiceChangeType: number;
|
||||
canConvert2Text: boolean;
|
||||
waveAmplitudes: number[];
|
||||
fileSubId: string;
|
||||
playState: number;
|
||||
autoConvertText: number;
|
||||
};
|
||||
}
|
||||
|
||||
export enum PicType {
|
||||
gif = 2000,
|
||||
jpg = 1000
|
||||
}
|
||||
|
||||
export enum PicSubType {
|
||||
normal = 0, // 普通图片,大图
|
||||
face = 1 // 表情包小图
|
||||
}
|
||||
|
||||
export interface SendPicElement {
|
||||
elementType: ElementType.PIC;
|
||||
elementId: string;
|
||||
picElement: {
|
||||
md5HexStr: string;
|
||||
fileSize: number | string;
|
||||
picWidth: number;
|
||||
picHeight: number;
|
||||
fileName: string;
|
||||
sourcePath: string;
|
||||
original: boolean;
|
||||
picType: PicType;
|
||||
picSubType: PicSubType;
|
||||
fileUuid: string;
|
||||
fileSubId: string;
|
||||
thumbFileSize: number;
|
||||
summary: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SendReplyElement {
|
||||
elementType: ElementType.REPLY;
|
||||
elementId: string;
|
||||
replyElement: {
|
||||
replayMsgSeq: string;
|
||||
replayMsgId: string;
|
||||
senderUin: string;
|
||||
senderUinStr: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface SendFaceElement {
|
||||
elementType: ElementType.FACE;
|
||||
elementId: string;
|
||||
faceElement: FaceElement;
|
||||
}
|
||||
|
||||
export interface SendMarketFaceElement {
|
||||
elementType: ElementType.MFACE;
|
||||
marketFaceElement: MarketFaceElement;
|
||||
}
|
||||
|
||||
export interface FileElement {
|
||||
fileMd5?: string;
|
||||
fileName: string;
|
||||
filePath: string;
|
||||
fileSize: string;
|
||||
picHeight?: number;
|
||||
picWidth?: number;
|
||||
folderId?: string;
|
||||
picThumbPath?: Map<number, string>;
|
||||
file10MMd5?: string;
|
||||
fileSha?: string;
|
||||
fileSha3?: string;
|
||||
fileUuid?: string;
|
||||
fileSubId?: string;
|
||||
thumbFileSize?: number;
|
||||
fileBizId?: number
|
||||
}
|
||||
|
||||
export interface SendFileElement {
|
||||
elementType: ElementType.FILE;
|
||||
elementId: string;
|
||||
fileElement: FileElement;
|
||||
}
|
||||
|
||||
export interface SendVideoElement {
|
||||
elementType: ElementType.VIDEO;
|
||||
elementId: string;
|
||||
videoElement: VideoElement;
|
||||
}
|
||||
|
||||
export interface SendArkElement {
|
||||
elementType: ElementType.ARK;
|
||||
elementId: string;
|
||||
arkElement: ArkElement;
|
||||
}
|
||||
|
||||
export interface SendMarkdownElement {
|
||||
elementType: ElementType.MARKDOWN;
|
||||
elementId: string;
|
||||
markdownElement: MarkdownElement;
|
||||
}
|
||||
|
||||
export type SendMessageElement = SendTextElement | SendPttElement |
|
||||
SendPicElement | SendReplyElement | SendFaceElement | SendMarketFaceElement | SendFileElement | SendVideoElement | SendArkElement | SendMarkdownElement
|
||||
|
||||
export enum AtType {
|
||||
notAt = 0,
|
||||
atAll = 1,
|
||||
atUser = 2
|
||||
}
|
||||
|
||||
export enum ChatType {
|
||||
friend = 1,
|
||||
group = 2,
|
||||
chatDevice = 8, //移动设备?
|
||||
temp = 100
|
||||
|
||||
}
|
||||
// 来自Android分析
|
||||
export enum ChatType2 {
|
||||
KCHATTYPEADELIE = 42,
|
||||
KCHATTYPEBUDDYNOTIFY = 5,
|
||||
KCHATTYPEC2C = 1,
|
||||
KCHATTYPECIRCLE = 113,
|
||||
KCHATTYPEDATALINE = 8,
|
||||
KCHATTYPEDATALINEMQQ = 134,
|
||||
KCHATTYPEDISC = 3,
|
||||
KCHATTYPEFAV = 41,
|
||||
KCHATTYPEGAMEMESSAGE = 105,
|
||||
KCHATTYPEGAMEMESSAGEFOLDER = 116,
|
||||
KCHATTYPEGROUP = 2,
|
||||
KCHATTYPEGROUPBLESS = 133,
|
||||
KCHATTYPEGROUPGUILD = 9,
|
||||
KCHATTYPEGROUPHELPER = 7,
|
||||
KCHATTYPEGROUPNOTIFY = 6,
|
||||
KCHATTYPEGUILD = 4,
|
||||
KCHATTYPEGUILDMETA = 16,
|
||||
KCHATTYPEMATCHFRIEND = 104,
|
||||
KCHATTYPEMATCHFRIENDFOLDER = 109,
|
||||
KCHATTYPENEARBY = 106,
|
||||
KCHATTYPENEARBYASSISTANT = 107,
|
||||
KCHATTYPENEARBYFOLDER = 110,
|
||||
KCHATTYPENEARBYHELLOFOLDER = 112,
|
||||
KCHATTYPENEARBYINTERACT = 108,
|
||||
KCHATTYPEQQNOTIFY = 132,
|
||||
KCHATTYPERELATEACCOUNT = 131,
|
||||
KCHATTYPESERVICEASSISTANT = 118,
|
||||
KCHATTYPESERVICEASSISTANTSUB = 201,
|
||||
KCHATTYPESQUAREPUBLIC = 115,
|
||||
KCHATTYPESUBSCRIBEFOLDER = 30,
|
||||
KCHATTYPETEMPADDRESSBOOK = 111,
|
||||
KCHATTYPETEMPBUSSINESSCRM = 102,
|
||||
KCHATTYPETEMPC2CFROMGROUP = 100,
|
||||
KCHATTYPETEMPC2CFROMUNKNOWN = 99,
|
||||
KCHATTYPETEMPFRIENDVERIFY = 101,
|
||||
KCHATTYPETEMPNEARBYPRO = 119,
|
||||
KCHATTYPETEMPPUBLICACCOUNT = 103,
|
||||
KCHATTYPETEMPWPA = 117,
|
||||
KCHATTYPEUNKNOWN = 0,
|
||||
KCHATTYPEWEIYUN = 40,
|
||||
}
|
||||
|
||||
export interface PttElement {
|
||||
canConvert2Text: boolean;
|
||||
duration: number; // 秒数
|
||||
fileBizId: null;
|
||||
fileId: number; // 0
|
||||
fileName: string; // "e4d09c784d5a2abcb2f9980bdc7acfe6.amr"
|
||||
filePath: string; // "/Users//Library/Containers/com.tencent.qq/Data/Library/Application Support/QQ/nt_qq_a6b15c9820595d25a56c1633ce19ad40/nt_data/Ptt/2023-11/Ori/e4d09c784d5a2abcb2f9980bdc7acfe6.amr"
|
||||
fileSize: string; // "4261"
|
||||
fileSubId: string; // "0"
|
||||
fileUuid: string; // "90j3z7rmRphDPrdVgP9udFBaYar#oK0TWZIV"
|
||||
formatType: string; // 1
|
||||
invalidState: number; // 0
|
||||
md5HexStr: string; // "e4d09c784d5a2abcb2f9980bdc7acfe6"
|
||||
playState: number; // 0
|
||||
progress: number; // 0
|
||||
text: string; // ""
|
||||
transferStatus: number; // 0
|
||||
translateStatus: number; // 0
|
||||
voiceChangeType: number; // 0
|
||||
voiceType: number; // 0
|
||||
waveAmplitudes: number[];
|
||||
}
|
||||
|
||||
export interface ArkElement {
|
||||
bytesData: string;
|
||||
linkInfo: null;
|
||||
subElementType: null;
|
||||
}
|
||||
|
||||
export const IMAGE_HTTP_HOST = 'https://gchat.qpic.cn';
|
||||
export const IMAGE_HTTP_HOST_NT = 'https://multimedia.nt.qq.com.cn';
|
||||
|
||||
export interface PicElement {
|
||||
picSubType?: number;
|
||||
originImageUrl: string; // http url, 没有host,host是https://gchat.qpic.cn/, 带download参数的是https://multimedia.nt.qq.com.cn
|
||||
originImageMd5?: string;
|
||||
sourcePath: string; // 图片本地路径
|
||||
thumbPath: Map<number, string>;
|
||||
picWidth: number;
|
||||
picHeight: number;
|
||||
fileSize: number;
|
||||
fileName: string;
|
||||
fileUuid: string;
|
||||
md5HexStr?: string;
|
||||
}
|
||||
|
||||
export enum GrayTipElementSubType {
|
||||
INVITE_NEW_MEMBER = 12,
|
||||
MEMBER_NEW_TITLE = 17
|
||||
}
|
||||
|
||||
export interface GrayTipElement {
|
||||
subElementType: GrayTipElementSubType;
|
||||
revokeElement: {
|
||||
operatorRole: string;
|
||||
operatorUid: string;
|
||||
operatorNick: string;
|
||||
operatorRemark: string;
|
||||
operatorMemRemark?: string;
|
||||
wording: string; // 自定义的撤回提示语
|
||||
}
|
||||
aioOpGrayTipElement: TipAioOpGrayTipElement;
|
||||
groupElement: TipGroupElement;
|
||||
xmlElement: {
|
||||
content: string;
|
||||
templId: string;
|
||||
};
|
||||
jsonGrayTipElement: {
|
||||
jsonStr: string;
|
||||
};
|
||||
}
|
||||
|
||||
export enum FaceType {
|
||||
normal = 1, // 小黄脸
|
||||
normal2 = 2, // 新小黄脸, 从faceIndex 222开始?
|
||||
dice = 3 // 骰子
|
||||
}
|
||||
export enum FaceIndex {
|
||||
dice = 358,
|
||||
RPS = 359 // 石头剪刀布
|
||||
}
|
||||
export interface FaceElement {
|
||||
faceIndex: number;
|
||||
faceType: FaceType;
|
||||
faceText?: string;
|
||||
packId?: string;
|
||||
stickerId?: string;
|
||||
sourceType?: number;
|
||||
stickerType?: number;
|
||||
resultId?: string;
|
||||
surpriseId?: string;
|
||||
randomType?: number;
|
||||
}
|
||||
|
||||
export interface MarketFaceElement {
|
||||
emojiPackageId: number;
|
||||
faceName: string;
|
||||
emojiId: string;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface VideoElement {
|
||||
filePath: string;
|
||||
fileName: string;
|
||||
videoMd5?: string;
|
||||
thumbMd5?: string
|
||||
fileTime?: number; // second
|
||||
thumbSize?: number; // byte
|
||||
fileFormat?: number; // 2表示mp4 参考下面条目
|
||||
fileSize?: string; // byte
|
||||
thumbWidth?: number;
|
||||
thumbHeight?: number;
|
||||
busiType?: 0; //
|
||||
subBusiType?: 0; // 未知
|
||||
thumbPath?: Map<number, any>;
|
||||
transferStatus?: 0; // 未知
|
||||
progress?: 0; // 下载进度?
|
||||
invalidState?: 0; // 未知
|
||||
fileUuid?: string; // 可以用于下载链接?
|
||||
fileSubId?: string;
|
||||
fileBizId?: null;
|
||||
originVideoMd5?: string;
|
||||
import_rich_media_context?: null;
|
||||
sourceVideoCodecFormat?: number;
|
||||
}
|
||||
// export enum busiType{
|
||||
// public static final int CREATOR_SHARE_ADV_XWORLD = 21;
|
||||
// public static final int MINI_APP_MINI_GAME = 11;
|
||||
// public static final int OFFICIAL_ACCOUNT_ADV = 4;
|
||||
// public static final int OFFICIAL_ACCOUNT_ADV_GAME = 8;
|
||||
// public static final int OFFICIAL_ACCOUNT_ADV_SHOP = 9;
|
||||
// public static final int OFFICIAL_ACCOUNT_ADV_VIP = 7;
|
||||
// public static final int OFFICIAL_ACCOUNT_LAYER_MASK_ADV = 14;
|
||||
// public static final int OFFICIAL_ACCOUNT_SPORT = 13;
|
||||
// public static final int OFFICIAL_ACCOUNT_TIAN_QI = 10;
|
||||
// public static final int PC_QQTAB_ADV = 18;
|
||||
// public static final int QIQIAOBAN_SDK = 15;
|
||||
// public static final int QQ_CPS = 16;
|
||||
// public static final int QQ_WALLET_CPS = 17;
|
||||
// public static final int QZONE_FEEDS = 0;
|
||||
// public static final int QZONE_PHOTO_TAIL = 2;
|
||||
// public static final int QZONE_VIDEO_LAYER = 1;
|
||||
// public static final int REWARD_GIFT_ADV = 6;
|
||||
// public static final int REWARD_GROUPGIFT_ADV = 12;
|
||||
// public static final int REWARD_PERSONAL_ADV = 5;
|
||||
// public static final int WEISEE_OFFICIAL_ACCOUNT = 3;
|
||||
// public static final int X_WORLD_CREATOR_ADV = 20;
|
||||
// public static final int X_WORLD_QZONE_LAYER = 22;
|
||||
// public static final int X_WORLD_VIDEO_ADV = 19;
|
||||
|
||||
// }
|
||||
// export enum CategoryBusiType {
|
||||
// _KCateBusiTypeDefault = 0,
|
||||
// _kCateBusiTypeFaceCluster = 1,
|
||||
// _kCateBusiTypeLabelCluster = 4,
|
||||
// _kCateBusiTypeMonthCluster = 16,
|
||||
// _kCateBusiTypePoiCluster = 2,
|
||||
// _kCateBusiTypeYearCluster = 8,
|
||||
// }
|
||||
export enum viedo_type {
|
||||
VIDEO_FORMAT_AFS = 7,
|
||||
VIDEO_FORMAT_AVI = 1,
|
||||
VIDEO_FORMAT_MKV = 4,
|
||||
VIDEO_FORMAT_MOD = 9,
|
||||
VIDEO_FORMAT_MOV = 8,
|
||||
VIDEO_FORMAT_MP4 = 2,
|
||||
VIDEO_FORMAT_MTS = 11,
|
||||
VIDEO_FORMAT_RM = 6,
|
||||
VIDEO_FORMAT_RMVB = 5,
|
||||
VIDEO_FORMAT_TS = 10,
|
||||
VIDEO_FORMAT_WMV = 3,
|
||||
}
|
||||
export interface MarkdownElement {
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface InlineKeyboardElementRowButton {
|
||||
id: string;
|
||||
label: string;
|
||||
visitedLabel: string;
|
||||
style: 1; // 未知
|
||||
type: 2; // 未知
|
||||
clickLimit: 0; // 未知
|
||||
unsupportTips: string;
|
||||
data: string;
|
||||
atBotShowChannelList: boolean;
|
||||
permissionType: number;
|
||||
specifyRoleIds: [];
|
||||
specifyTinyids: [];
|
||||
isReply: false;
|
||||
anchor: 0;
|
||||
enter: false;
|
||||
subscribeDataTemplateIds: []
|
||||
}
|
||||
|
||||
export interface InlineKeyboardElement {
|
||||
rows: [{
|
||||
buttons: InlineKeyboardElementRowButton[]
|
||||
}];
|
||||
}
|
||||
|
||||
export interface TipAioOpGrayTipElement { // 这是什么提示来着?
|
||||
operateType: number;
|
||||
peerUid: string;
|
||||
fromGrpCodeOfTmpChat: string;
|
||||
}
|
||||
|
||||
export enum TipGroupElementType {
|
||||
memberIncrease = 1,
|
||||
kicked = 3, // 被移出群
|
||||
ban = 8
|
||||
}
|
||||
// public final class MemberAddShowType {
|
||||
// public static final int KOTHERADD = 0;
|
||||
// public static final int KOTHERADDBYOTHERQRCODE = 2;
|
||||
// public static final int KOTHERADDBYYOURQRCODE = 3;
|
||||
// public static final int KOTHERINVITEOTHER = 5;
|
||||
// public static final int KOTHERINVITEYOU = 6;
|
||||
// public static final int KYOUADD = 1;
|
||||
// public static final int KYOUADDBYOTHERQRCODE = 4;
|
||||
// public static final int KYOUALREADYMEMBER = 8;
|
||||
// public static final int KYOUINVITEOTHER = 7;
|
||||
// }
|
||||
export interface TipGroupElement {
|
||||
type: TipGroupElementType; // 1是表示有人加入群; 自己加入群也会收到这个
|
||||
role: 0; // 暂时不知
|
||||
groupName: string; // 暂时获取不到
|
||||
memberUid: string;
|
||||
memberNick: string;
|
||||
memberRemark: string;
|
||||
adminUid: string;
|
||||
adminNick: string;
|
||||
adminRemark: string;
|
||||
createGroup: null;
|
||||
memberAdd?: {
|
||||
showType: 1;
|
||||
otherAdd: null;
|
||||
otherAddByOtherQRCode: null;
|
||||
otherAddByYourQRCode: null;
|
||||
youAddByOtherQRCode: null;
|
||||
otherInviteOther: null;
|
||||
otherInviteYou: null;
|
||||
youInviteOther: null
|
||||
};
|
||||
shutUp?: {
|
||||
curTime: string;
|
||||
duration: string; // 禁言时间,秒
|
||||
admin: {
|
||||
uid: string;
|
||||
card: string;
|
||||
name: string;
|
||||
role: GroupMemberRole
|
||||
};
|
||||
member: {
|
||||
uid: string
|
||||
card: string;
|
||||
name: string;
|
||||
role: GroupMemberRole
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface MultiForwardMsgElement {
|
||||
xmlContent: string; // xml格式的消息内容
|
||||
resId: string;
|
||||
fileName: string;
|
||||
}
|
||||
|
||||
export interface RawMessage {
|
||||
// int32, 自己维护的消息id
|
||||
id?: number;
|
||||
|
||||
msgId: string;
|
||||
|
||||
// 时间戳,秒
|
||||
msgTime: string;
|
||||
|
||||
msgSeq: string;
|
||||
msgType: number;
|
||||
subMsgType: number;
|
||||
senderUid: string;
|
||||
senderUin: string; // 发送者QQ号
|
||||
peerUid: string; // 群号 或者 QQ uid
|
||||
peerUin: string; // 群号 或者 发送者QQ号
|
||||
sendNickName: string;
|
||||
sendMemberName?: string; // 发送者群名片
|
||||
chatType: ChatType;
|
||||
sendStatus?: number; // 消息状态,别人发的2是已撤回,自己发的2是已发送
|
||||
recallTime: string; // 撤回时间, "0"是没有撤回
|
||||
elements: {
|
||||
elementId: string;
|
||||
elementType: ElementType;
|
||||
replyElement: {
|
||||
senderUid: string; // 原消息发送者QQ号
|
||||
sourceMsgIsIncPic: boolean; // 原消息是否有图片
|
||||
sourceMsgText: string;
|
||||
replayMsgSeq: string; // 源消息的msgSeq,可以通过这个找到源消息的msgId
|
||||
};
|
||||
textElement: {
|
||||
atType: AtType;
|
||||
atUid: string; // QQ号
|
||||
content: string;
|
||||
atNtUid: string; // uid号
|
||||
};
|
||||
picElement: PicElement;
|
||||
pttElement: PttElement;
|
||||
arkElement: ArkElement;
|
||||
grayTipElement: GrayTipElement;
|
||||
faceElement: FaceElement;
|
||||
videoElement: VideoElement;
|
||||
fileElement: FileElement;
|
||||
marketFaceElement: MarketFaceElement;
|
||||
inlineKeyboardElement: InlineKeyboardElement;
|
||||
markdownElement: MarkdownElement;
|
||||
multiForwardMsgElement: MultiForwardMsgElement;
|
||||
}[];
|
||||
}
|
||||
115
src/core/src/entities/notify.ts
Normal file
115
src/core/src/entities/notify.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
export enum GroupNotifyTypes {
|
||||
INVITE_ME = 1,
|
||||
INVITED_JOIN = 4, // 有人接受了邀请入群
|
||||
JOIN_REQUEST = 7,
|
||||
ADMIN_SET = 8,
|
||||
KICK_MEMBER = 9,
|
||||
MEMBER_EXIT = 11, // 主动退出
|
||||
ADMIN_UNSET = 12,
|
||||
ADMIN_UNSET_OTHER = 13, // 其他人取消管理员
|
||||
}
|
||||
|
||||
export interface GroupNotifies {
|
||||
doubt: boolean;
|
||||
nextStartSeq: string;
|
||||
notifies: GroupNotify[];
|
||||
}
|
||||
|
||||
export enum GroupNotifyStatus {
|
||||
IGNORE = 0,
|
||||
WAIT_HANDLE = 1,
|
||||
APPROVE = 2,
|
||||
REJECT = 3
|
||||
}
|
||||
|
||||
export interface GroupNotify {
|
||||
time: number; // 自己添加的字段,时间戳,毫秒, 用于判断收到短时间内收到重复的notify
|
||||
seq: string; // 唯一标识符,转成数字再除以1000应该就是时间戳?
|
||||
type: GroupNotifyTypes;
|
||||
status: GroupNotifyStatus; // 0是已忽略?,1是未处理,2是已同意
|
||||
group: { groupCode: string; groupName: string };
|
||||
user1: { uid: string; nickName: string }; // 被设置管理员的人
|
||||
user2: { uid: string; nickName: string }; // 操作者
|
||||
actionUser: { uid: string; nickName: string }; //未知
|
||||
actionTime: string;
|
||||
invitationExt: {
|
||||
srcType: number; // 0?未知
|
||||
groupCode: string; waitStatus: number
|
||||
};
|
||||
postscript: string; // 加群用户填写的验证信息
|
||||
repeatSeqs: [];
|
||||
warningTips: string
|
||||
}
|
||||
|
||||
export enum GroupRequestOperateTypes {
|
||||
approve = 1,
|
||||
reject = 2
|
||||
}
|
||||
export enum BuddyReqType {
|
||||
KMEINITIATOR,
|
||||
KPEERINITIATOR,
|
||||
KMEAGREED,
|
||||
KMEAGREEDANDADDED,
|
||||
KPEERAGREED,
|
||||
KPEERAGREEDANDADDED,
|
||||
KPEERREFUSED,
|
||||
KMEREFUSED,
|
||||
KMEIGNORED,
|
||||
KMEAGREEANYONE,
|
||||
KMESETQUESTION,
|
||||
KMEAGREEANDADDFAILED,
|
||||
KMSGINFO,
|
||||
KMEINITIATORWAITPEERCONFIRM
|
||||
}
|
||||
export interface FriendRequest {
|
||||
isDecide: boolean;
|
||||
friendUid: string;
|
||||
reqType: BuddyReqType,
|
||||
reqTime: string; // 时间戳;秒
|
||||
extWords: string; // 申请人填写的验证消息
|
||||
isUnread: boolean;
|
||||
friendNick: string;
|
||||
sourceId: number;
|
||||
groupCode: string
|
||||
}
|
||||
|
||||
export interface FriendRequestNotify {
|
||||
unreadNums: number;
|
||||
buddyReqs: FriendRequest[];
|
||||
}
|
||||
export enum MemberExtSourceType {
|
||||
DEFAULTTYPE = 0,
|
||||
TITLETYPE = 1,
|
||||
NEWGROUPTYPE = 2,
|
||||
}
|
||||
export interface GroupExtParam {
|
||||
groupCode: string
|
||||
seq: string
|
||||
beginUin: string
|
||||
dataTime: string
|
||||
uinList: Array<string>
|
||||
uinNum: string
|
||||
groupType: string
|
||||
richCardNameVer: string
|
||||
sourceType: MemberExtSourceType
|
||||
memberExtFilter: {
|
||||
memberLevelInfoUin: number
|
||||
memberLevelInfoPoint: number
|
||||
memberLevelInfoActiveDay: number
|
||||
memberLevelInfoLevel: number
|
||||
memberLevelInfoName: number
|
||||
levelName: number
|
||||
dataTime: number
|
||||
userShowFlag: number
|
||||
sysShowFlag: number
|
||||
timeToUpdate: number
|
||||
nickName: number
|
||||
specialTitle: number
|
||||
levelNameNew: number
|
||||
userShowFlagNew: number
|
||||
msgNeedField: number
|
||||
cmdUinFlagExt3Grocery: number
|
||||
memberIcon: number
|
||||
memberInfoSeq: number
|
||||
}
|
||||
}
|
||||
162
src/core/src/entities/user.ts
Normal file
162
src/core/src/entities/user.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
export enum Sex {
|
||||
male = 1,
|
||||
female = 2,
|
||||
unknown = 255,
|
||||
}
|
||||
export interface BuddyCategoryType {
|
||||
categoryId: number;
|
||||
categroyName: string;
|
||||
categroyMbCount: number;
|
||||
buddyList: User[];
|
||||
}
|
||||
|
||||
export interface ModifyProfileParams {
|
||||
nick: string,
|
||||
longNick: string,
|
||||
sex: Sex,
|
||||
birthday: { birthday_year: string, birthday_month: string, birthday_day: string },
|
||||
location: any//undefined
|
||||
}
|
||||
|
||||
export interface BuddyProfileLikeReq {
|
||||
friendUids: string[];
|
||||
basic: number;
|
||||
vote: number;
|
||||
favorite: number;
|
||||
userProfile: number;
|
||||
type: number;
|
||||
start: number;
|
||||
limit: number;
|
||||
}
|
||||
export interface QQLevel {
|
||||
crownNum: number;
|
||||
sunNum: number;
|
||||
moonNum: number;
|
||||
starNum: number
|
||||
}
|
||||
export interface User {
|
||||
uid: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
nick: string;
|
||||
avatarUrl?: string;
|
||||
longNick?: string; // 签名
|
||||
remark?: string;
|
||||
sex?: Sex;
|
||||
qqLevel?: QQLevel;
|
||||
qid?: string
|
||||
birthday_year?: number;
|
||||
birthday_month?: number;
|
||||
birthday_day?: number;
|
||||
topTime?: string;
|
||||
constellation?: number;
|
||||
shengXiao?: number;
|
||||
kBloodType?: number;
|
||||
homeTown?: string; //"0-0-0";
|
||||
makeFriendCareer?: number;
|
||||
pos?: string;
|
||||
eMail?: string
|
||||
phoneNum?: string;
|
||||
college?: string;
|
||||
country?: string;
|
||||
province?: string;
|
||||
city?: string;
|
||||
postCode?: string;
|
||||
address?: string;
|
||||
isBlock?: boolean;
|
||||
isSpecialCareOpen?: boolean;
|
||||
isSpecialCareZone?: boolean;
|
||||
ringId?: string;
|
||||
regTime?: number;
|
||||
interest?: string;
|
||||
labels?: string[];
|
||||
isHideQQLevel?: number;
|
||||
privilegeIcon?: {
|
||||
jumpUrl: string;
|
||||
openIconList: unknown[];
|
||||
closeIconList: unknown[]
|
||||
};
|
||||
photoWall?: {
|
||||
picList: unknown[]
|
||||
};
|
||||
vipFlag?: boolean;
|
||||
yearVipFlag?: boolean;
|
||||
svipFlag?: boolean;
|
||||
vipLevel?: number;
|
||||
status?: number;
|
||||
qidianMasterFlag?: number;
|
||||
qidianCrewFlag?: number;
|
||||
qidianCrewFlag2?: number;
|
||||
extStatus?: number;
|
||||
recommendImgFlag?: number;
|
||||
disableEmojiShortCuts?: number;
|
||||
pendantId?: string;
|
||||
}
|
||||
|
||||
export interface SelfInfo extends User {
|
||||
online?: boolean;
|
||||
}
|
||||
|
||||
export interface Friend extends User { }
|
||||
|
||||
export enum BizKey {
|
||||
KPRIVILEGEICON,
|
||||
KPHOTOWALL
|
||||
}
|
||||
export interface UserDetailInfoByUin {
|
||||
result: number,
|
||||
errMsg: string,
|
||||
info: {
|
||||
uid: string,//这个没办法用
|
||||
qid: string,
|
||||
uin: string,
|
||||
nick: string,
|
||||
remark: string,
|
||||
longNick: string,
|
||||
avatarUrl: string,
|
||||
birthday_year: number,
|
||||
birthday_month: number,
|
||||
birthday_day: number,
|
||||
sex: number,//0
|
||||
topTime: string,
|
||||
constellation: number,
|
||||
shengXiao: number,
|
||||
kBloodType: number,
|
||||
homeTown: string,
|
||||
makeFriendCareer: number,
|
||||
pos: string,
|
||||
eMail: string,
|
||||
phoneNum: string,
|
||||
college: string,
|
||||
country: string,
|
||||
province: string,
|
||||
city: string,
|
||||
postCode: string,
|
||||
address: string,
|
||||
isBlock: boolean,
|
||||
isSpecialCareOpen: boolean,
|
||||
isSpecialCareZone: boolean,
|
||||
ringId: string,
|
||||
regTime: number,
|
||||
interest: string,
|
||||
termType: number,
|
||||
labels: any[],
|
||||
qqLevel: { crownNum: number, sunNum: number, moonNum: number, starNum: number },
|
||||
isHideQQLevel: number,
|
||||
privilegeIcon: { jumpUrl: string, openIconList: any[], closeIconList: any[] },
|
||||
isHidePrivilegeIcon: number,
|
||||
photoWall: { picList: any[] },
|
||||
vipFlag: boolean,
|
||||
yearVipFlag: boolean,
|
||||
svipFlag: boolean,
|
||||
vipLevel: number,
|
||||
status: number,
|
||||
qidianMasterFlag: number,
|
||||
qidianCrewFlag: number,
|
||||
qidianCrewFlag2: number,
|
||||
extStatus: number,
|
||||
recommendImgFlag: number,
|
||||
disableEmojiShortCuts: number,
|
||||
pendantId: string,
|
||||
vipNameColorId: string
|
||||
}
|
||||
}
|
||||
18
src/core/src/index.ts
Normal file
18
src/core/src/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import QQWrapper from './wrapper';
|
||||
|
||||
export * from './adapters';
|
||||
export * from './apis';
|
||||
export * from './entities';
|
||||
export * from './listeners';
|
||||
export * from './services';
|
||||
|
||||
export * as Adapters from './adapters';
|
||||
export * as APIs from './apis';
|
||||
export * as Entities from './entities';
|
||||
export * as Listeners from './listeners';
|
||||
export * as Services from './services';
|
||||
export { QQWrapper as Wrapper };
|
||||
export * as WrapperInterface from './wrapper';
|
||||
export * as SessionConfig from './sessionConfig';
|
||||
|
||||
export { napCatCore } from './core';
|
||||
97
src/core/src/listeners/NodeIKernelBuddyListener.ts
Normal file
97
src/core/src/listeners/NodeIKernelBuddyListener.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { BuddyCategoryType, FriendRequestNotify } from '@/core/entities';
|
||||
|
||||
export type OnBuddyChangeParams = BuddyCategoryType[]
|
||||
|
||||
interface IBuddyListener {
|
||||
onBuddyListChange(arg: OnBuddyChangeParams): void,
|
||||
|
||||
onBuddyInfoChange(arg: unknown): void,
|
||||
|
||||
onBuddyDetailInfoChange(arg: unknown): void,
|
||||
|
||||
onNickUpdated(arg: unknown): void,
|
||||
|
||||
onBuddyRemarkUpdated(arg: unknown): void,
|
||||
|
||||
onAvatarUrlUpdated(arg: unknown): void,
|
||||
|
||||
onBuddyReqChange(arg: FriendRequestNotify): void,
|
||||
|
||||
onBuddyReqUnreadCntChange(arg: unknown): void,
|
||||
|
||||
onCheckBuddySettingResult(arg: unknown): void,
|
||||
|
||||
onAddBuddyNeedVerify(arg: unknown): void,
|
||||
|
||||
onSmartInfos(arg: unknown): void,
|
||||
|
||||
onSpacePermissionInfos(arg: unknown): void,
|
||||
|
||||
onDoubtBuddyReqChange(arg: unknown): void,
|
||||
|
||||
onDoubtBuddyReqUnreadNumChange(arg: unknown): void,
|
||||
|
||||
onBlockChanged(arg: unknown): void,
|
||||
|
||||
onAddMeSettingChanged(arg: unknown): void,
|
||||
|
||||
onDelBatchBuddyInfos(arg: unknown): void
|
||||
}
|
||||
|
||||
export interface NodeIKernelBuddyListener extends IBuddyListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(listener: IBuddyListener): NodeIKernelBuddyListener;
|
||||
}
|
||||
|
||||
export class BuddyListener implements IBuddyListener {
|
||||
onAddBuddyNeedVerify(arg: unknown) {
|
||||
}
|
||||
|
||||
onAddMeSettingChanged(arg: unknown) {
|
||||
}
|
||||
|
||||
onAvatarUrlUpdated(arg: unknown) {
|
||||
}
|
||||
|
||||
onBlockChanged(arg: unknown) {
|
||||
}
|
||||
|
||||
onBuddyDetailInfoChange(arg: unknown) {
|
||||
}
|
||||
|
||||
onBuddyInfoChange(arg: unknown) {
|
||||
}
|
||||
|
||||
onBuddyListChange(arg: OnBuddyChangeParams): void {
|
||||
}
|
||||
|
||||
onBuddyRemarkUpdated(arg: unknown): void {
|
||||
}
|
||||
|
||||
onBuddyReqChange(arg: FriendRequestNotify): void {
|
||||
}
|
||||
|
||||
onBuddyReqUnreadCntChange(arg: unknown): void {
|
||||
}
|
||||
|
||||
onCheckBuddySettingResult(arg: unknown): void {
|
||||
}
|
||||
|
||||
onDelBatchBuddyInfos(arg: unknown): void {
|
||||
}
|
||||
|
||||
onDoubtBuddyReqChange(arg: unknown): void {
|
||||
}
|
||||
|
||||
onDoubtBuddyReqUnreadNumChange(arg: unknown): void {
|
||||
}
|
||||
|
||||
onNickUpdated(arg: unknown): void {
|
||||
}
|
||||
|
||||
onSmartInfos(arg: unknown): void {
|
||||
}
|
||||
|
||||
onSpacePermissionInfos(arg: unknown): void {
|
||||
}
|
||||
}
|
||||
27
src/core/src/listeners/NodeIKernelFileAssistantListener.ts
Normal file
27
src/core/src/listeners/NodeIKernelFileAssistantListener.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
export interface IKernelFileAssistantListener {
|
||||
onFileStatusChanged(...args: unknown[]): unknown;
|
||||
|
||||
onSessionListChanged(...args: unknown[]): unknown;
|
||||
|
||||
onSessionChanged(...args: unknown[]): unknown;
|
||||
|
||||
onFileListChanged(...args: unknown[]): unknown;
|
||||
|
||||
onFileSearch(...args: unknown[]): unknown;
|
||||
}
|
||||
export interface NodeIKernelFileAssistantListener extends IKernelFileAssistantListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(adapter: IKernelFileAssistantListener): NodeIKernelFileAssistantListener;
|
||||
}
|
||||
|
||||
export class KernelFileAssistantListener implements IKernelFileAssistantListener {
|
||||
onFileStatusChanged(...args: unknown[]) { }
|
||||
|
||||
onSessionListChanged(...args: unknown[]) { }
|
||||
|
||||
onSessionChanged(...args: unknown[]) { }
|
||||
|
||||
onFileListChanged(...args: unknown[]) { }
|
||||
|
||||
onFileSearch(...args: unknown[]) { }
|
||||
}
|
||||
240
src/core/src/listeners/NodeIKernelGroupListener.ts
Normal file
240
src/core/src/listeners/NodeIKernelGroupListener.ts
Normal file
@@ -0,0 +1,240 @@
|
||||
import { Group, GroupMember, GroupNotify } from '@/core/entities';
|
||||
|
||||
interface IGroupListener {
|
||||
onGroupListUpdate(updateType: number, groupList: Group[]): void;
|
||||
|
||||
onGroupExtListUpdate(...args: unknown[]): void;
|
||||
|
||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void;
|
||||
|
||||
onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]): void;
|
||||
|
||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void;
|
||||
|
||||
onGroupDetailInfoChange(...args: unknown[]): void;
|
||||
|
||||
onGroupAllInfoChange(...args: unknown[]): void;
|
||||
|
||||
onGroupsMsgMaskResult(...args: unknown[]): void;
|
||||
|
||||
onGroupConfMemberChange(...args: unknown[]): void;
|
||||
|
||||
onGroupBulletinChange(...args: unknown[]): void;
|
||||
|
||||
onGetGroupBulletinListResult(...args: unknown[]): void;
|
||||
|
||||
onMemberListChange(arg: {
|
||||
sceneId: string,
|
||||
ids: string[],
|
||||
infos: Map<string, GroupMember>,
|
||||
finish: boolean,
|
||||
hasRobot: boolean
|
||||
}): void;
|
||||
|
||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>): void;
|
||||
|
||||
onSearchMemberChange(...args: unknown[]): void;
|
||||
|
||||
onGroupBulletinRichMediaDownloadComplete(...args: unknown[]): void;
|
||||
|
||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]): void;
|
||||
|
||||
onGroupStatisticInfoChange(...args: unknown[]): void;
|
||||
|
||||
onJoinGroupNotify(...args: unknown[]): void;
|
||||
|
||||
onShutUpMemberListChanged(...args: unknown[]): void;
|
||||
|
||||
onGroupBulletinRemindNotify(...args: unknown[]): void;
|
||||
|
||||
onGroupFirstBulletinNotify(...args: unknown[]): void;
|
||||
|
||||
onJoinGroupNoVerifyFlag(...args: unknown[]): void;
|
||||
|
||||
onGroupArkInviteStateResult(...args: unknown[]): void;
|
||||
// 发现于Win 9.9.9 23159
|
||||
onGroupMemberLevelInfoChange(...args: unknown[]): void;
|
||||
}
|
||||
|
||||
export interface NodeIKernelGroupListener extends IGroupListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(listener: IGroupListener): NodeIKernelGroupListener;
|
||||
}
|
||||
|
||||
export class GroupListener implements IGroupListener {
|
||||
// 发现于Win 9.9.9 23159
|
||||
onGroupMemberLevelInfoChange(...args: unknown[]): void {
|
||||
|
||||
}
|
||||
onGetGroupBulletinListResult(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupAllInfoChange(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupBulletinChange(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupBulletinRemindNotify(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupArkInviteStateResult(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupBulletinRichMediaDownloadComplete(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupConfMemberChange(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupDetailInfoChange(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupExtListUpdate(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupFirstBulletinNotify(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupListUpdate(updateType: number, groupList: Group[]) {
|
||||
}
|
||||
|
||||
onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]) {
|
||||
}
|
||||
|
||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]) {
|
||||
}
|
||||
|
||||
onGroupsMsgMaskResult(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onGroupStatisticInfoChange(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onJoinGroupNotify(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onJoinGroupNoVerifyFlag(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>) {
|
||||
}
|
||||
|
||||
onMemberListChange(arg: {
|
||||
sceneId: string,
|
||||
ids: string[],
|
||||
infos: Map<string, GroupMember>, // uid -> GroupMember
|
||||
finish: boolean,
|
||||
hasRobot: boolean
|
||||
}) {
|
||||
}
|
||||
|
||||
onSearchMemberChange(...args: unknown[]) {
|
||||
}
|
||||
|
||||
onShutUpMemberListChanged(...args: unknown[]) {
|
||||
}
|
||||
}
|
||||
|
||||
export class DebugGroupListener implements IGroupListener {
|
||||
onGroupMemberLevelInfoChange(...args: unknown[]): void {
|
||||
console.log('onGroupMemberLevelInfoChange:', ...args);
|
||||
}
|
||||
onGetGroupBulletinListResult(...args: unknown[]) {
|
||||
console.log('onGetGroupBulletinListResult:', ...args);
|
||||
}
|
||||
|
||||
onGroupAllInfoChange(...args: unknown[]) {
|
||||
console.log('onGroupAllInfoChange:', ...args);
|
||||
}
|
||||
|
||||
onGroupBulletinChange(...args: unknown[]) {
|
||||
console.log('onGroupBulletinChange:', ...args);
|
||||
}
|
||||
|
||||
onGroupBulletinRemindNotify(...args: unknown[]) {
|
||||
console.log('onGroupBulletinRemindNotify:', ...args);
|
||||
}
|
||||
|
||||
onGroupArkInviteStateResult(...args: unknown[]) {
|
||||
console.log('onGroupArkInviteStateResult:', ...args);
|
||||
}
|
||||
|
||||
onGroupBulletinRichMediaDownloadComplete(...args: unknown[]) {
|
||||
console.log('onGroupBulletinRichMediaDownloadComplete:', ...args);
|
||||
}
|
||||
|
||||
onGroupConfMemberChange(...args: unknown[]) {
|
||||
console.log('onGroupConfMemberChange:', ...args);
|
||||
}
|
||||
|
||||
onGroupDetailInfoChange(...args: unknown[]) {
|
||||
console.log('onGroupDetailInfoChange:', ...args);
|
||||
}
|
||||
|
||||
onGroupExtListUpdate(...args: unknown[]) {
|
||||
console.log('onGroupExtListUpdate:', ...args);
|
||||
}
|
||||
|
||||
onGroupFirstBulletinNotify(...args: unknown[]) {
|
||||
console.log('onGroupFirstBulletinNotify:', ...args);
|
||||
}
|
||||
|
||||
onGroupListUpdate(...args: unknown[]) {
|
||||
console.log('onGroupListUpdate:', ...args);
|
||||
}
|
||||
|
||||
onGroupNotifiesUpdated(...args: unknown[]) {
|
||||
console.log('onGroupNotifiesUpdated:', ...args);
|
||||
}
|
||||
|
||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]) {
|
||||
console.log('onGroupBulletinRichMediaProgressUpdate:', ...args);
|
||||
}
|
||||
|
||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]) {
|
||||
console.log('onGroupNotifiesUnreadCountUpdated:', ...args);
|
||||
}
|
||||
|
||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]){
|
||||
console.log('onGroupSingleScreenNotifies:');
|
||||
}
|
||||
|
||||
onGroupsMsgMaskResult(...args: unknown[]) {
|
||||
console.log('onGroupsMsgMaskResult:', ...args);
|
||||
}
|
||||
|
||||
onGroupStatisticInfoChange(...args: unknown[]) {
|
||||
console.log('onGroupStatisticInfoChange:', ...args);
|
||||
}
|
||||
|
||||
onJoinGroupNotify(...args: unknown[]) {
|
||||
console.log('onJoinGroupNotify:', ...args);
|
||||
}
|
||||
|
||||
onJoinGroupNoVerifyFlag(...args: unknown[]) {
|
||||
console.log('onJoinGroupNoVerifyFlag:', ...args);
|
||||
}
|
||||
|
||||
onMemberInfoChange(groupCode: string, changeType: number, members: Map<string, GroupMember>) {
|
||||
console.log('onMemberInfoChange:', groupCode, changeType, members);
|
||||
}
|
||||
|
||||
onMemberListChange(...args: unknown[]) {
|
||||
console.log('onMemberListChange:', ...args);
|
||||
}
|
||||
|
||||
onSearchMemberChange(...args: unknown[]) {
|
||||
console.log('onSearchMemberChange:', ...args);
|
||||
}
|
||||
|
||||
onShutUpMemberListChanged(...args: unknown[]) {
|
||||
console.log('onShutUpMemberListChanged:', ...args);
|
||||
}
|
||||
}
|
||||
108
src/core/src/listeners/NodeIKernelLoginListener.ts
Normal file
108
src/core/src/listeners/NodeIKernelLoginListener.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
export interface IKernelLoginListener {
|
||||
onLoginConnected(...args: any[]): void;
|
||||
|
||||
onLoginDisConnected(...args: any[]): void;
|
||||
|
||||
onLoginConnecting(...args: any[]): void;
|
||||
|
||||
onQRCodeGetPicture(...args: any[]): void;
|
||||
|
||||
onQRCodeLoginPollingStarted(...args: any[]): void;
|
||||
|
||||
onQRCodeSessionUserScaned(...args: any[]): void;
|
||||
|
||||
onQRCodeLoginSucceed(...args: any[]): void;
|
||||
|
||||
onQRCodeSessionFailed(...args: any[]): void;
|
||||
|
||||
onLoginFailed(...args: any[]): void;
|
||||
|
||||
onLogoutSucceed(...args: any[]): void;
|
||||
|
||||
onLogoutFailed(...args: any[]): void;
|
||||
|
||||
onUserLoggedIn(...args: any[]): void;
|
||||
|
||||
onQRCodeSessionQuickLoginFailed(...args: any[]): void;
|
||||
|
||||
onPasswordLoginFailed(...args: any[]): void;
|
||||
|
||||
OnConfirmUnusualDeviceFailed(...args: any[]): void;
|
||||
|
||||
onQQLoginNumLimited(...args: any[]): void;
|
||||
|
||||
onLoginState(...args: any[]): void;
|
||||
}
|
||||
|
||||
export interface NodeIKernelLoginListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(listener: IKernelLoginListener): NodeIKernelLoginListener;
|
||||
}
|
||||
|
||||
export class LoginListener implements IKernelLoginListener {
|
||||
onLoginConnected(...args: any[]): void {
|
||||
}
|
||||
|
||||
onLoginDisConnected(...args: any[]): void {
|
||||
}
|
||||
|
||||
onLoginConnecting(...args: any[]): void {
|
||||
}
|
||||
|
||||
onQRCodeGetPicture(arg: { pngBase64QrcodeData: string, qrcodeUrl: string }): void {
|
||||
// let base64Data: string = arg.pngBase64QrcodeData
|
||||
// base64Data = base64Data.split("data:image/png;base64,")[1]
|
||||
// let buffer = Buffer.from(base64Data, 'base64')
|
||||
// console.log("onQRCodeGetPicture", arg);
|
||||
}
|
||||
|
||||
onQRCodeLoginPollingStarted(...args: any[]): void {
|
||||
}
|
||||
|
||||
onQRCodeSessionUserScaned(...args: any[]): void {
|
||||
}
|
||||
|
||||
onQRCodeLoginSucceed(arg: QRCodeLoginSucceedResult): void {
|
||||
}
|
||||
|
||||
onQRCodeSessionFailed(...args: any[]): void {
|
||||
}
|
||||
|
||||
onLoginFailed(...args: any[]): void {
|
||||
}
|
||||
|
||||
onLogoutSucceed(...args: any[]): void {
|
||||
}
|
||||
|
||||
onLogoutFailed(...args: any[]): void {
|
||||
}
|
||||
|
||||
onUserLoggedIn(...args: any[]): void {
|
||||
}
|
||||
|
||||
onQRCodeSessionQuickLoginFailed(...args: any[]): void {
|
||||
}
|
||||
|
||||
onPasswordLoginFailed(...args: any[]): void {
|
||||
}
|
||||
|
||||
OnConfirmUnusualDeviceFailed(...args: any[]): void {
|
||||
}
|
||||
|
||||
onQQLoginNumLimited(...args: any[]): void {
|
||||
}
|
||||
|
||||
onLoginState(...args: any[]): void {
|
||||
}
|
||||
}
|
||||
|
||||
export interface QRCodeLoginSucceedResult {
|
||||
account: string;
|
||||
mainAccount: string;
|
||||
uin: string; //拿UIN
|
||||
uid: string; //拿UID
|
||||
nickName: string; //一般是空的 拿不到
|
||||
gender: number;
|
||||
age: number;
|
||||
faceUrl: string;//一般是空的 拿不到
|
||||
}
|
||||
478
src/core/src/listeners/NodeIKernelMsgListener.ts
Normal file
478
src/core/src/listeners/NodeIKernelMsgListener.ts
Normal file
@@ -0,0 +1,478 @@
|
||||
import { ChatType, RawMessage } from '@/core/entities';
|
||||
|
||||
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<any>
|
||||
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: unknown): 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 {
|
||||
// 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[]) {
|
||||
|
||||
}
|
||||
}
|
||||
40
src/core/src/listeners/NodeIKernelProfileListener.ts
Normal file
40
src/core/src/listeners/NodeIKernelProfileListener.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { User } from '@/core/entities';
|
||||
|
||||
interface IProfileListener {
|
||||
onProfileSimpleChanged(...args: unknown[]): void;
|
||||
|
||||
onProfileDetailInfoChanged(profile: User): void;
|
||||
|
||||
onStatusUpdate(...args: unknown[]): void;
|
||||
|
||||
onSelfStatusChanged(...args: unknown[]): void;
|
||||
|
||||
onStrangerRemarkChanged(...args: unknown[]): void;
|
||||
}
|
||||
|
||||
export interface NodeIKernelProfileListener extends IProfileListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(listener: IProfileListener): NodeIKernelProfileListener;
|
||||
}
|
||||
|
||||
export class ProfileListener implements IProfileListener {
|
||||
onProfileSimpleChanged(...args: unknown[]) {
|
||||
|
||||
}
|
||||
|
||||
onProfileDetailInfoChanged(profile: User) {
|
||||
|
||||
}
|
||||
|
||||
onStatusUpdate(...args: unknown[]) {
|
||||
|
||||
}
|
||||
|
||||
onSelfStatusChanged(...args: unknown[]) {
|
||||
|
||||
}
|
||||
|
||||
onStrangerRemarkChanged(...args: unknown[]) {
|
||||
|
||||
}
|
||||
}
|
||||
28
src/core/src/listeners/NodeIKernelRobotListener.ts
Normal file
28
src/core/src/listeners/NodeIKernelRobotListener.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
export interface IKernelRobotListener {
|
||||
onRobotFriendListChanged(...args: unknown[]): void;
|
||||
|
||||
onRobotListChanged(...args: unknown[]): void;
|
||||
|
||||
onRobotProfileChanged(...args: unknown[]): void;
|
||||
}
|
||||
|
||||
export interface NodeIKernelRobotListener extends IKernelRobotListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(adapter: IKernelRobotListener): NodeIKernelRobotListener;
|
||||
}
|
||||
|
||||
export class KernelRobotListener implements IKernelRobotListener {
|
||||
onRobotFriendListChanged(...args: unknown[]){
|
||||
|
||||
}
|
||||
|
||||
onRobotListChanged(...args: unknown[]){
|
||||
|
||||
}
|
||||
|
||||
onRobotProfileChanged(...args: unknown[]){
|
||||
|
||||
}
|
||||
}
|
||||
44
src/core/src/listeners/NodeIKernelSessionListener.ts
Normal file
44
src/core/src/listeners/NodeIKernelSessionListener.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
export interface ISessionListener {
|
||||
onNTSessionCreate(args: unknown): void;
|
||||
|
||||
onGProSessionCreate(args: unknown): void;
|
||||
|
||||
onSessionInitComplete(args: unknown): void;
|
||||
|
||||
onOpentelemetryInit(args: unknown): void;
|
||||
|
||||
onUserOnlineResult(args: unknown): void;
|
||||
|
||||
onGetSelfTinyId(args: unknown): void;
|
||||
}
|
||||
|
||||
export interface NodeIKernelSessionListener extends ISessionListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(adapter: ISessionListener): NodeIKernelSessionListener;
|
||||
}
|
||||
|
||||
export class SessionListener implements ISessionListener {
|
||||
onNTSessionCreate(args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
onGProSessionCreate(args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
onSessionInitComplete(args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
onOpentelemetryInit(args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
onUserOnlineResult(args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
onGetSelfTinyId(args: unknown) {
|
||||
|
||||
}
|
||||
}
|
||||
37
src/core/src/listeners/NodeIKernelStorageCleanListener.ts
Normal file
37
src/core/src/listeners/NodeIKernelStorageCleanListener.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export interface IStorageCleanListener {
|
||||
onCleanCacheProgressChanged(args: unknown): void;
|
||||
|
||||
onScanCacheProgressChanged(args: unknown): void;
|
||||
|
||||
onCleanCacheStorageChanged(args: unknown): void;
|
||||
|
||||
onFinishScan(args: unknown): void;
|
||||
|
||||
onChatCleanDone(args: unknown): void;
|
||||
|
||||
}
|
||||
export interface NodeIKernelStorageCleanListener extends IStorageCleanListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(adapter: IStorageCleanListener): NodeIKernelStorageCleanListener;
|
||||
}
|
||||
|
||||
export class StorageCleanListener implements IStorageCleanListener {
|
||||
onCleanCacheProgressChanged(args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
onScanCacheProgressChanged(args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
onCleanCacheStorageChanged(args: unknown) {
|
||||
|
||||
}
|
||||
onFinishScan(args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
onChatCleanDone(args: unknown) {
|
||||
|
||||
}
|
||||
}
|
||||
9
src/core/src/listeners/NodeIKernelTicketListener.ts
Normal file
9
src/core/src/listeners/NodeIKernelTicketListener.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export interface IKernelTicketListener {
|
||||
}
|
||||
export interface NodeIKernelTicketListener extends IKernelTicketListener {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(adapter: IKernelTicketListener): NodeIKernelTicketListener;
|
||||
}
|
||||
|
||||
export class KernelTicketListener implements IKernelTicketListener {
|
||||
}
|
||||
12
src/core/src/listeners/index.ts
Normal file
12
src/core/src/listeners/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
export * from './NodeIKernelSessionListener';
|
||||
export * from './NodeIKernelLoginListener';
|
||||
export * from './NodeIKernelMsgListener';
|
||||
export * from './NodeIKernelGroupListener';
|
||||
export * from './NodeIKernelBuddyListener';
|
||||
export * from './NodeIKernelProfileListener';
|
||||
export * from './NodeIKernelRobotListener';
|
||||
export * from './NodeIKernelTicketListener';
|
||||
export * from './NodeIKernelStorageCleanListener';
|
||||
export * from './NodeIKernelFileAssistantListener';
|
||||
|
||||
46
src/core/src/services/NodeIKernelAlbumService.ts
Normal file
46
src/core/src/services/NodeIKernelAlbumService.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
export interface NodeIKernelAlbumService {
|
||||
setAlbumServiceInfo(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
getMainPage(...args: any[]): unknown;// needs 2 arguments
|
||||
|
||||
getAlbumList(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
getAlbumInfo(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
deleteAlbum(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
addAlbum(...args: any[]): unknown;// needs 2 arguments
|
||||
|
||||
deleteMedias(...args: any[]): unknown;// needs 4 arguments
|
||||
|
||||
modifyAlbum(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
getMediaList(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
quoteToQzone(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
quoteToQunAlbum(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
queryQuoteToQunAlbumStatus(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
getQunFeeds(...args: any[]): unknown;//needs 1 arguments
|
||||
|
||||
getQunFeedDetail(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
getQunNoticeList(...args: any[]): unknown;// needs 4 arguments
|
||||
|
||||
getQunComment(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
getQunLikes(...args: any[]): unknown;// needs 4 arguments
|
||||
|
||||
deleteQunFeed(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
doQunComment(...args: any[]): unknown;// needs 6 arguments
|
||||
|
||||
doQunReply(...args: any[]): unknown;// needs 7 arguments
|
||||
|
||||
doQunLike(...args: any[]): unknown;// needs 5 arguments
|
||||
|
||||
getRedPoints(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
}
|
||||
31
src/core/src/services/NodeIKernelAvatarService.ts
Normal file
31
src/core/src/services/NodeIKernelAvatarService.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
export interface NodeIKernelAvatarService {
|
||||
addAvatarListener(arg: unknown): unknown;
|
||||
|
||||
removeAvatarListener(arg: unknown): unknown;
|
||||
|
||||
getAvatarPath(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
forceDownloadAvatar(uid: string, useCache: number): Promise<unknown>;
|
||||
|
||||
getGroupAvatarPath(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
getConfGroupAvatarPath(arg: unknown): unknown;
|
||||
|
||||
forceDownloadGroupAvatar(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
getGroupPortraitPath(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
forceDownloadGroupPortrait(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
getAvatarPaths(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
getGroupAvatarPaths(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
getConfGroupAvatarPaths(arg: unknown): unknown;
|
||||
|
||||
getAvatarPathByUin(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
forceDownloadAvatarByUin(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
103
src/core/src/services/NodeIKernelBuddyService.ts
Normal file
103
src/core/src/services/NodeIKernelBuddyService.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { Friend } from '@/core/entities';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
import { NodeIKernelBuddyListener } from '@/core/listeners';
|
||||
|
||||
export interface NodeIKernelBuddyService {
|
||||
// 以下为自行添加的,wrapper.node中并没有这些方法,目的是简化调用
|
||||
friends: Friend[];
|
||||
|
||||
getFriend(uidOrUin: string): Promise<Friend>;
|
||||
|
||||
// 以下为原生方法
|
||||
addKernelBuddyListener(listener: NodeIKernelBuddyListener): number;
|
||||
|
||||
removeKernelBuddyListener(listener: unknown): void;
|
||||
|
||||
getBuddyList(bool: boolean): Promise<GeneralCallResult>;
|
||||
|
||||
getBuddyNick(uid: number): string;
|
||||
|
||||
getBuddyRemark(uid: number): string;
|
||||
|
||||
setBuddyRemark(uid: number, remark: string): void;
|
||||
|
||||
getAvatarUrl(uid: number): string;
|
||||
|
||||
isBuddy(uid: string): boolean;
|
||||
|
||||
getCategoryNameWithUid(uid: number): string;
|
||||
|
||||
getTargetBuddySetting(uid: number): unknown;
|
||||
|
||||
getTargetBuddySettingByType(uid: number, type: number): unknown;
|
||||
|
||||
getBuddyReqUnreadCnt(): number;
|
||||
|
||||
getBuddyReq(): unknown;
|
||||
|
||||
delBuddyReq(uid: number): void;
|
||||
|
||||
clearBuddyReqUnreadCnt(): void;
|
||||
|
||||
reqToAddFriends(uid: number, msg: string): void;
|
||||
|
||||
setSpacePermission(uid: number, permission: number): void;
|
||||
|
||||
approvalFriendRequest(arg: {
|
||||
friendUid: string;
|
||||
reqTime: string;
|
||||
accept: boolean;
|
||||
}): Promise<void>;
|
||||
|
||||
delBuddy(uid: number): void;
|
||||
|
||||
delBatchBuddy(uids: number[]): void;
|
||||
|
||||
getSmartInfos(uid: number): unknown;
|
||||
|
||||
setBuddyCategory(uid: number, category: number): void;
|
||||
|
||||
setBatchBuddyCategory(uids: number[], category: number): void;
|
||||
|
||||
addCategory(category: string): void;
|
||||
|
||||
delCategory(category: string): void;
|
||||
|
||||
renameCategory(oldCategory: string, newCategory: string): void;
|
||||
|
||||
resortCategory(categorys: string[]): void;
|
||||
|
||||
pullCategory(uid: number, category: string): void;
|
||||
|
||||
setTop(uid: number, isTop: boolean): void;
|
||||
|
||||
SetSpecialCare(uid: number, isSpecialCare: boolean): void;
|
||||
|
||||
setMsgNotify(uid: number, isNotify: boolean): void;
|
||||
|
||||
hasBuddyList(): boolean;
|
||||
|
||||
setBlock(uid: number, isBlock: boolean): void;
|
||||
|
||||
isBlocked(uid: number): boolean;
|
||||
|
||||
modifyAddMeSetting(setting: unknown): void;
|
||||
|
||||
getAddMeSetting(): unknown;
|
||||
|
||||
getDoubtBuddyReq(): unknown;
|
||||
|
||||
getDoubtBuddyUnreadNum(): number;
|
||||
|
||||
approvalDoubtBuddyReq(uid: number, isAgree: boolean): void;
|
||||
|
||||
delDoubtBuddyReq(uid: number): void;
|
||||
|
||||
delAllDoubtBuddyReq(): void;
|
||||
|
||||
reportDoubtBuddyReqUnread(): void;
|
||||
|
||||
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<unknown>;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
91
src/core/src/services/NodeIKernelCollectionService.ts
Normal file
91
src/core/src/services/NodeIKernelCollectionService.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { GeneralCallResult } from "./common";
|
||||
|
||||
export interface NodeIKernelCollectionService {
|
||||
addKernelCollectionListener(...args: any[]): unknown;//needs 1 arguments
|
||||
|
||||
removeKernelCollectionListener(...args: any[]): unknown;//needs 1 arguments
|
||||
|
||||
getCollectionItemList(param: {
|
||||
category: number,
|
||||
groupId: number,
|
||||
forceSync: boolean,
|
||||
forceFromDb: boolean,
|
||||
timeStamp: string,
|
||||
count: number,
|
||||
searchDown: boolean
|
||||
}): Promise<GeneralCallResult &
|
||||
{
|
||||
collectionSearchList: {
|
||||
collectionItemList: Array<
|
||||
{
|
||||
cid: string,
|
||||
type: number,
|
||||
status: number,
|
||||
author: {
|
||||
type: number,
|
||||
numId: string,
|
||||
strId: string,
|
||||
groupId: string,
|
||||
groupName: string,
|
||||
uid: string
|
||||
},
|
||||
bid: number,
|
||||
category: number,
|
||||
createTime: string,
|
||||
collectTime: string,
|
||||
modifyTime: string,
|
||||
sequence: string,
|
||||
shareUrl: string,
|
||||
customGroupId: number,
|
||||
securityBeat: boolean,
|
||||
summary: {
|
||||
textSummary: unknown,
|
||||
linkSummary: unknown,
|
||||
gallerySummary: unknown,
|
||||
audioSummary: unknown,
|
||||
videoSummary: unknown,
|
||||
fileSummary: unknown,
|
||||
locationSummary: unknown,
|
||||
richMediaSummary: unknown,
|
||||
}
|
||||
}>,
|
||||
hasMore: boolean,
|
||||
bottomTimeStamp: string
|
||||
}
|
||||
}
|
||||
>;//needs 1 arguments
|
||||
|
||||
getCollectionContent(...args: any[]): unknown;//needs 5 arguments
|
||||
|
||||
getCollectionCustomGroupList(...args: any[]): unknown;//needs 0 arguments
|
||||
|
||||
getCollectionUserInfo(...args: any[]): unknown;//needs 0 arguments
|
||||
|
||||
searchCollectionItemList(...args: any[]): unknown;//needs 2 arguments
|
||||
|
||||
addMsgToCollection(...args: any[]): unknown;//needs 2 arguments
|
||||
|
||||
collectionArkShare(...args: any[]): unknown;//needs 1 arguments
|
||||
|
||||
collectionFileForward(...args: any[]): unknown;//needs 3 arguments
|
||||
|
||||
downloadCollectionFile(...args: any[]): unknown;//needs 4 arguments
|
||||
|
||||
downloadCollectionFileThumbPic(...args: any[]): unknown;//needs 4 arguments
|
||||
|
||||
downloadCollectionPic(...args: any[]): unknown;//needs 3 arguments
|
||||
|
||||
cancelDownloadCollectionFile(...args: any[]): unknown;//needs 1 arguments
|
||||
|
||||
deleteCollectionItemList(...args: any[]): unknown;//needs 1 arguments
|
||||
|
||||
editCollectionItem(...args: any[]): unknown;//needs 2 arguments
|
||||
|
||||
getEditPicInfoByPath(...args: any[]): unknown;//needs 1 arguments
|
||||
|
||||
collectionFastUpload(...args: any[]): unknown;//needs 1 arguments
|
||||
|
||||
editCollectionItemAfterFastUpload(...args: any[]): unknown;//needs 2 arguments
|
||||
|
||||
createNewCollectionItem(...args: any[]): unknown;//needs 1 arguments
|
||||
}
|
||||
5
src/core/src/services/NodeIKernelDbToolsService.ts
Normal file
5
src/core/src/services/NodeIKernelDbToolsService.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface NodeIKernelDbToolsService {
|
||||
depositDatabase(...args: unknown[]): unknown;
|
||||
backupDatabase(...args: unknown[]): unknown;
|
||||
retrieveDatabase(...args: unknown[]): unknown;
|
||||
}
|
||||
35
src/core/src/services/NodeIKernelFileAssistantService.ts
Normal file
35
src/core/src/services/NodeIKernelFileAssistantService.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export interface NodeIKernelFileAssistantService {
|
||||
addKernelFileAssistantListener(arg1: unknown[]): unknown;
|
||||
|
||||
removeKernelFileAssistantListener(arg1: unknown[]): unknown;
|
||||
|
||||
getFileAssistantList(arg1: unknown[]): unknown;
|
||||
|
||||
getMoreFileAssistantList(arg1: unknown[]): unknown;
|
||||
|
||||
getFileSessionList(): unknown;
|
||||
|
||||
searchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
resetSearchFileSortType(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
searchMoreFile(arg1: unknown[]): unknown;
|
||||
|
||||
cancelSearchFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
downloadFile(arg1: unknown[]): unknown;
|
||||
|
||||
forwardFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
cancelFileAction(arg1: unknown[]): unknown;
|
||||
|
||||
retryFileAction(arg1: unknown[]): unknown;
|
||||
|
||||
deleteFile(arg1: unknown[]): unknown;
|
||||
|
||||
saveAs(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
saveAsWithRename(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
153
src/core/src/services/NodeIKernelGroupService.ts
Normal file
153
src/core/src/services/NodeIKernelGroupService.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { NodeIKernelGroupListener } from '@/core/listeners/NodeIKernelGroupListener';
|
||||
import {
|
||||
GroupExtParam,
|
||||
GroupMember,
|
||||
GroupMemberRole,
|
||||
GroupNotifyTypes,
|
||||
GroupRequestOperateTypes,
|
||||
} from '@/core/entities';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
|
||||
export interface NodeIKernelGroupService {
|
||||
|
||||
addKernelGroupListener(listener: NodeIKernelGroupListener): number;
|
||||
|
||||
removeKernelGroupListener(listenerId: unknown): void;
|
||||
|
||||
createMemberListScene(groupCode: string, scene: string): string;
|
||||
|
||||
destroyMemberListScene(): void;
|
||||
//About Arg (a) name: lastId 根据手Q来看为object {index:?(number),uid:string}
|
||||
getNextMemberList(sceneId: string, a: undefined, num: number): Promise<{
|
||||
errCode: number, errMsg: string,
|
||||
result: { ids: string[], infos: Map<string, GroupMember>, finish: boolean, hasRobot: boolean }
|
||||
}>;
|
||||
|
||||
getPrevMemberList(): unknown;
|
||||
|
||||
monitorMemberList(): unknown;
|
||||
|
||||
searchMember(uid: string): unknown;
|
||||
|
||||
getMemberInfo(uid: string): unknown;
|
||||
//getMemberInfo [ '56729xxxx', [ 'u_4Nj08cwW5Hxxxxx' ], true ]
|
||||
|
||||
kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise<void>;
|
||||
|
||||
modifyMemberRole(groupCode: string, uid: string, role: GroupMemberRole): void;
|
||||
|
||||
modifyMemberCardName(groupCode: string, uid: string, cardName: string): void;
|
||||
|
||||
getTransferableMemberInfo(uid: string): unknown;
|
||||
|
||||
transferGroup(uid: string): void;
|
||||
|
||||
getGroupList(force: boolean): Promise<GeneralCallResult>;
|
||||
|
||||
getGroupExtList(force: boolean): Promise<GeneralCallResult>;
|
||||
|
||||
getGroupDetailInfo(groupCode: string): unknown;
|
||||
|
||||
getMemberExtInfo(param: GroupExtParam): Promise<unknown>;//req
|
||||
|
||||
getGroupAllInfo(): unknown;
|
||||
|
||||
getDiscussExistInfo(): unknown;
|
||||
|
||||
getGroupConfMember(): unknown;
|
||||
|
||||
getGroupMsgMask(): unknown;
|
||||
|
||||
getGroupPortrait(): void;
|
||||
|
||||
modifyGroupName(groupCode: string, groupName: string, arg: false): void;
|
||||
|
||||
modifyGroupRemark(groupCode: string, remark: string): void;
|
||||
|
||||
modifyGroupDetailInfo(groupCode: string, arg: unknown): void;
|
||||
|
||||
setGroupMsgMask(groupCode: string, arg: unknown): void;
|
||||
|
||||
changeGroupShieldSettingTemp(groupCode: string, arg: unknown): void;
|
||||
|
||||
inviteToGroup(arg: unknown): void;
|
||||
|
||||
inviteMembersToGroup(args: unknown[]): void;
|
||||
|
||||
inviteMembersToGroupWithMsg(args: unknown): void;
|
||||
|
||||
createGroup(arg: unknown): void;
|
||||
|
||||
createGroupWithMembers(arg: unknown): void;
|
||||
|
||||
quitGroup(groupCode: string): void;
|
||||
|
||||
destroyGroup(groupCode: string): void;
|
||||
//获取单屏群通知列表
|
||||
getSingleScreenNotifies(force: boolean, start_seq: string, num: number): Promise<GeneralCallResult>;
|
||||
|
||||
clearGroupNotifies(groupCode: string): void;
|
||||
|
||||
getGroupNotifiesUnreadCount(unknown: Boolean): Promise<GeneralCallResult>;
|
||||
|
||||
clearGroupNotifiesUnreadCount(groupCode: string): void;
|
||||
|
||||
operateSysNotify(
|
||||
doubt: boolean,
|
||||
operateMsg: {
|
||||
operateType: GroupRequestOperateTypes, // 2 拒绝
|
||||
targetMsg: {
|
||||
seq: string, // 通知序列号
|
||||
type: GroupNotifyTypes,
|
||||
groupCode: string,
|
||||
postscript: string
|
||||
}
|
||||
}): Promise<void>;
|
||||
|
||||
setTop(groupCode: string, isTop: boolean): void;
|
||||
|
||||
getGroupBulletin(groupCode: string): unknown;
|
||||
|
||||
deleteGroupBulletin(groupCode: string, seq: string): void;
|
||||
|
||||
publishGroupBulletin(groupCode: string, pskey: string, data: any): Promise<GeneralCallResult>;
|
||||
|
||||
publishInstructionForNewcomers(groupCode: string, arg: unknown): void;
|
||||
|
||||
uploadGroupBulletinPic(groupCode: string, pskey: string, imagePath: string): Promise<GeneralCallResult & {
|
||||
errCode: number;
|
||||
picInfo?: {
|
||||
id: string,
|
||||
width: number,
|
||||
height: number
|
||||
}
|
||||
}>;
|
||||
|
||||
downloadGroupBulletinRichMedia(groupCode: string): unknown;
|
||||
|
||||
getGroupBulletinList(groupCode: string): unknown;
|
||||
|
||||
getGroupStatisticInfo(groupCode: string): unknown;
|
||||
|
||||
getGroupRemainAtTimes(groupCode: string): number;
|
||||
|
||||
getJoinGroupNoVerifyFlag(groupCode: string): unknown;
|
||||
|
||||
getGroupArkInviteState(groupCode: string): unknown;
|
||||
|
||||
reqToJoinGroup(groupCode: string, arg: unknown): void;
|
||||
|
||||
setGroupShutUp(groupCode: string, shutUp: boolean): void;
|
||||
|
||||
getGroupShutUpMemberList(groupCode: string): unknown[];
|
||||
|
||||
setMemberShutUp(groupCode: string, memberTimes: { uid: string, timeStamp: number }[]): Promise<void>;
|
||||
|
||||
getGroupRecommendContactArkJson(groupCode: string): unknown;
|
||||
|
||||
getJoinGroupLink(groupCode: string): unknown;
|
||||
|
||||
modifyGroupExtInfo(groupCode: string, arg: unknown): void;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
82
src/core/src/services/NodeIKernelLoginService.ts
Normal file
82
src/core/src/services/NodeIKernelLoginService.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { NodeIKernelLoginListener } from '@/core/listeners/NodeIKernelLoginListener';
|
||||
|
||||
export interface LoginInitConfig {
|
||||
machineId: '';
|
||||
appid: string;
|
||||
platVer: string;
|
||||
commonPath: string;
|
||||
clientVer: string;
|
||||
hostName: string;
|
||||
}
|
||||
|
||||
export interface passwordLoginRetType {
|
||||
result: string,
|
||||
loginErrorInfo: {
|
||||
step: number;
|
||||
errMsg: string;
|
||||
proofWaterUrl: string;
|
||||
newDevicePullQrCodeSig: string;
|
||||
jumpUrl: string,
|
||||
jumpWord: string;
|
||||
tipsTitle: string;
|
||||
tipsContent: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface passwordLoginArgType {
|
||||
uin: string;
|
||||
passwordMd5: string;//passwMD5
|
||||
step: number;//猜测是需要二次认证 参数 一次为0
|
||||
newDeviceLoginSig: string;
|
||||
proofWaterSig: string;
|
||||
proofWaterRand: string;
|
||||
proofWaterSid: string;
|
||||
}
|
||||
|
||||
export interface LoginListItem {
|
||||
uin: string;
|
||||
uid: string;
|
||||
nickName: string;
|
||||
faceUrl: string;
|
||||
facePath: string;
|
||||
loginType: 1; // 1是二维码登录?
|
||||
isQuickLogin: boolean; // 是否可以快速登录
|
||||
isAutoLogin: boolean; // 是否可以自动登录
|
||||
}
|
||||
|
||||
export interface QuickLoginResult{
|
||||
result: string
|
||||
loginErrorInfo: {
|
||||
step: number,
|
||||
errMsg: string,
|
||||
proofWaterUrl: string,
|
||||
newDevicePullQrCodeSig: string,
|
||||
jumpUrl: string,
|
||||
jumpWord: string,
|
||||
tipsTitle: string,
|
||||
tipsContent: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface NodeIKernelLoginService {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(): NodeIKernelLoginService;
|
||||
|
||||
addKernelLoginListener(listener: NodeIKernelLoginListener): number;
|
||||
removeKernelLoginListener(listener: number): void;
|
||||
|
||||
initConfig(config: LoginInitConfig): void;
|
||||
|
||||
getLoginMiscData(cb: (r: unknown) => void): void;
|
||||
|
||||
getLoginList(): Promise<{
|
||||
result: number, // 0是ok
|
||||
LocalLoginInfoList: LoginListItem[]
|
||||
}>;
|
||||
|
||||
quickLoginWithUin(uin: string): Promise<QuickLoginResult>;
|
||||
|
||||
passwordLogin(param: passwordLoginArgType): Promise<any>;
|
||||
|
||||
getQRCodePicture(): boolean;
|
||||
}
|
||||
27
src/core/src/services/NodeIKernelMsgBackupService.ts
Normal file
27
src/core/src/services/NodeIKernelMsgBackupService.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
export interface NodeIKernelMsgBackupService {
|
||||
addKernelMsgBackupListener(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
removeKernelMsgBackupListener(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
getMsgBackupLocation(...args: any[]): unknown;// needs 0 arguments
|
||||
|
||||
setMsgBackupLocation(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
requestMsgBackup(...args: any[]): unknown;// needs 0 arguments
|
||||
|
||||
requestMsgRestore(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
requestMsgMigrate(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
getLocalStorageBackup(...args: any[]): unknown;// needs 0 arguments
|
||||
|
||||
deleteLocalBackup(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
clearCache(...args: any[]): unknown;// needs 0 arguments
|
||||
|
||||
start(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
stop(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
pause(...args: any[]): unknown;// needs 2 arguments
|
||||
}
|
||||
666
src/core/src/services/NodeIKernelMsgService.ts
Normal file
666
src/core/src/services/NodeIKernelMsgService.ts
Normal file
@@ -0,0 +1,666 @@
|
||||
import { ChatType, ElementType, Peer, RawMessage, SendMessageElement } from '@/core/entities';
|
||||
import { NodeIKernelMsgListener } from '@/core/listeners/NodeIKernelMsgListener';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
|
||||
export interface NodeIKernelMsgService {
|
||||
addKernelMsgListener(nodeIKernelMsgListener: NodeIKernelMsgListener): number;
|
||||
|
||||
sendMsg(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>): Promise<unknown>;
|
||||
|
||||
recallMsg(peer: Peer, msgIds: string[]): Promise<GeneralCallResult>;
|
||||
|
||||
addKernelMsgImportToolListener(arg: Object): unknown;
|
||||
|
||||
removeKernelMsgListener(args: unknown): unknown;
|
||||
|
||||
addKernelTempChatSigListener(...args: unknown[]): unknown;
|
||||
|
||||
removeKernelTempChatSigListener(...args: unknown[]): unknown;
|
||||
|
||||
setAutoReplyTextList(AutoReplyText: Array<unknown>, i2: number): unknown;
|
||||
|
||||
getAutoReplyTextList(...args: unknown[]): unknown;
|
||||
|
||||
getOnLineDev(): Promise<any>;
|
||||
|
||||
kickOffLine(DevInfo: Object): unknown;
|
||||
|
||||
setStatus(args: { status: number, extStatus: number, batteryStatus: number }): Promise<GeneralCallResult>;
|
||||
|
||||
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(...args: unknown[]): unknown;
|
||||
|
||||
reqToOfflineSendMsg(...args: unknown[]): unknown;
|
||||
|
||||
refuseReceiveOnlineFileMsg(peer: Peer, MsgId: string): unknown;
|
||||
|
||||
resendMsg(...args: unknown[]): unknown;
|
||||
|
||||
recallMsg(...args: unknown[]): unknown;
|
||||
|
||||
reeditRecallMsg(...args: unknown[]): unknown;
|
||||
|
||||
forwardMsg(...args: unknown[]): Promise<GeneralCallResult>;
|
||||
|
||||
forwardMsgWithComment(...args: unknown[]): unknown;
|
||||
|
||||
forwardSubMsgWithComment(...args: unknown[]): unknown;
|
||||
|
||||
forwardRichMsgInVist(...args: unknown[]): unknown;
|
||||
|
||||
forwardFile(...args: unknown[]): unknown;
|
||||
//Array<Msg>, 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(...args: unknown[]): unknown;
|
||||
|
||||
deleteMsg(...args: unknown[]): unknown;
|
||||
|
||||
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<unknown>;
|
||||
|
||||
getLastMessageList(peer: Peer[]): Promise<unknown>;
|
||||
|
||||
getAioFirstViewLatestMsgs(...args: unknown[]): unknown;
|
||||
|
||||
getMsgs(peer: Peer, msgId: string, count: unknown, queryOrder: boolean): Promise<unknown>;
|
||||
|
||||
getMsgsIncludeSelf(peer: Peer, msgId: string, count: number, queryOrder: boolean): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[]
|
||||
}>;
|
||||
|
||||
// this.$peer = contact;
|
||||
// this.$msgTime = j2;
|
||||
// this.$clientSeq = j3;
|
||||
// this.$cnt = i2;
|
||||
|
||||
getMsgsWithMsgTimeAndClientSeqForC2C(...args: unknown[]): Promise<unknown>;
|
||||
|
||||
getMsgsWithStatus(params: {
|
||||
peer: Peer
|
||||
msgId: string
|
||||
msgTime: unknown
|
||||
cnt: unknown
|
||||
queryOrder: boolean
|
||||
isIncludeSelf: boolean
|
||||
appid: unknown
|
||||
}): Promise<unknown>;
|
||||
|
||||
getMsgsBySeqRange(peer: Peer, startSeq: string, endSeq: string): Promise<unknown>;
|
||||
|
||||
getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, unknownArg: boolean): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||
|
||||
getMsgsByMsgId(peer: Peer, ids: string[]): Promise<GeneralCallResult & { msgList: RawMessage[] }>;
|
||||
|
||||
getRecallMsgsByMsgId(peer: Peer, MsgId: string[]): Promise<unknown>;
|
||||
|
||||
getMsgsBySeqList(peer: Peer, seqList: string[]): Promise<unknown>;
|
||||
|
||||
getSingleMsg(Peer: Peer, msgSeq: string): unknown;
|
||||
|
||||
getSourceOfReplyMsg(...args: unknown[]): unknown;
|
||||
|
||||
getSourceOfReplyMsgV2(...args: unknown[]): unknown;
|
||||
|
||||
getMsgByClientSeqAndTime(...args: unknown[]): unknown;
|
||||
|
||||
getSourceOfReplyMsgByClientSeqAndTime(...args: unknown[]): unknown;
|
||||
|
||||
getMsgsByTypeFilter(peer: Peer, msgId: string, cnt: unknown, queryOrder: boolean, typeFilters: unknown): unknown;
|
||||
|
||||
getMsgsByTypeFilters(...args: unknown[]): unknown;
|
||||
|
||||
getMsgWithAbstractByFilterParam(...args: unknown[]): unknown;
|
||||
|
||||
queryMsgsWithFilter(...args: unknown[]): unknown;
|
||||
|
||||
queryMsgsWithFilterVer2(MsgId: string, MsgTime: string, param: {
|
||||
chatInfo: {
|
||||
chatType: number,
|
||||
peerUid: string
|
||||
},
|
||||
filterMsgType: [],
|
||||
filterSendersUid: [],
|
||||
filterMsgFromTime: string,
|
||||
filterMsgToTime: string,
|
||||
pageLimit: number,
|
||||
isReverseOrder: boolean,
|
||||
isIncludeCurrent: boolean
|
||||
}): Promise<unknown>;
|
||||
// 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: {
|
||||
chatInfo: {
|
||||
chatType: number,
|
||||
peerUid: string
|
||||
},
|
||||
filterMsgType: [],
|
||||
filterSendersUid: [],
|
||||
filterMsgFromTime: string,
|
||||
filterMsgToTime: string,
|
||||
pageLimit: number,
|
||||
isReverseOrder: boolean,
|
||||
isIncludeCurrent: boolean
|
||||
|
||||
}): Promise<unknown>;
|
||||
//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: {
|
||||
chatInfo: {
|
||||
chatType: number,
|
||||
peerUid: string
|
||||
},
|
||||
filterMsgType: [],
|
||||
filterSendersUid: [],
|
||||
filterMsgFromTime: string,
|
||||
filterMsgToTime: string,
|
||||
pageLimit: number,
|
||||
isReverseOrder: boolean,
|
||||
isIncludeCurrent: boolean
|
||||
}):Promise<unknown>;
|
||||
|
||||
queryPicOrVideoMsgsDesktop(...args: unknown[]): unknown;
|
||||
|
||||
queryEmoticonMsgs(...args: unknown[]): unknown;
|
||||
|
||||
queryTroopEmoticonMsgs(...args: unknown[]): unknown;
|
||||
|
||||
queryMsgsAndAbstractsWithFilter(...args: unknown[]): 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<GeneralCallResult>;
|
||||
|
||||
setAllC2CAndGroupMsgRead(...args: unknown[]): unknown;
|
||||
|
||||
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(...args: unknown[]): 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(...args: unknown[]): unknown;
|
||||
|
||||
setPttPlayedState(...args: unknown[]): unknown;
|
||||
|
||||
fetchFavEmojiList(...args: unknown[]): unknown;
|
||||
|
||||
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(...args: unknown[]): 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: unknown[]): 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(...args: unknown[]): unknown;
|
||||
|
||||
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<unknown>;
|
||||
|
||||
queryCalendar(...args: unknown[]): unknown;
|
||||
|
||||
queryFirstMsgSeq(...args: unknown[]): unknown;
|
||||
|
||||
queryRoamCalendar(...args: unknown[]): unknown;
|
||||
|
||||
queryFirstRoamMsg(...args: unknown[]): unknown;
|
||||
|
||||
fetchLongMsg(...args: unknown[]): unknown;
|
||||
|
||||
fetchLongMsgWithCb(...args: unknown[]): unknown;
|
||||
|
||||
setIsStopKernelFetchLongMsg(...args: unknown[]): unknown;
|
||||
|
||||
insertGameResultAsMsgToDb(...args: unknown[]): unknown;
|
||||
|
||||
getMultiMsg(...args: unknown[]): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[]
|
||||
}>;
|
||||
|
||||
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(...args: unknown[]): 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(...args: unknown[]): 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;//主动临时消息 不做
|
||||
|
||||
//chattype,uid->Promise<any>
|
||||
getTempChatInfo(ChatType: number, Uid: string): unknown;
|
||||
|
||||
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<unknown>;//频道的东西
|
||||
|
||||
outputGuildUnreadInfo(...args: unknown[]): unknown;
|
||||
|
||||
checkMsgWithUrl(...args: unknown[]): unknown;
|
||||
|
||||
checkTabListStatus(...args: unknown[]): unknown;
|
||||
|
||||
getABatchOfContactMsgBoxInfo(...args: unknown[]): unknown;
|
||||
|
||||
insertMsgToMsgBox(...args: unknown[]): unknown;
|
||||
|
||||
isHitEmojiKeyword(...args: unknown[]): unknown;
|
||||
|
||||
getKeyWordRelatedEmoji(...args: unknown[]): unknown;
|
||||
|
||||
recordEmoji(...args: unknown[]): unknown;
|
||||
|
||||
fetchGetHitEmotionsByWord(args: Object): Promise<unknown>;//表情推荐?
|
||||
|
||||
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(...args: unknown[]): 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;//这是嘛啊
|
||||
|
||||
}
|
||||
12
src/core/src/services/NodeIKernelNodeMiscService.ts
Normal file
12
src/core/src/services/NodeIKernelNodeMiscService.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { GeneralCallResult } from "./common";
|
||||
|
||||
//没扒干净 因为用不着
|
||||
export interface NodeIKernelNodeMiscService {
|
||||
getMiniAppPath(): unknown;
|
||||
setMiniAppVersion(version:string): unknown;
|
||||
wantWinScreenOCR(imagepath: string): Promise<GeneralCallResult>;
|
||||
SendMiniAppMsg(arg1: string, arg2: string, arg3: string): unknown;
|
||||
startNewMiniApp(appfile: string, params: string): unknown;
|
||||
// 我的计划是转发给一个新程序避免吃掉Electron_AS_Node的环境 然后重写启动MiniApp 挂载相应JS脚本 这样有个问题
|
||||
// 需要自己转发ipc参数 然后必须处在gui环境 且完成校验破解 才能实现发包 有点抽象了
|
||||
}
|
||||
36
src/core/src/services/NodeIKernelOnlineStatusService.ts
Normal file
36
src/core/src/services/NodeIKernelOnlineStatusService.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
export interface NodeIKernelOnlineStatusService {
|
||||
|
||||
addKernelOnlineStatusListener(listener: unknown): void;
|
||||
|
||||
removeKernelOnlineStatusListener(listenerId: unknown): void;
|
||||
|
||||
getShouldShowAIOStatusAnimation(arg: unknown): unknown;
|
||||
|
||||
setReadLikeList(arg: unknown): unknown;
|
||||
|
||||
getLikeList(arg: unknown): unknown;
|
||||
|
||||
setLikeStatus(arg: unknown): unknown;
|
||||
|
||||
getAggregationPageEntrance(): unknown;
|
||||
|
||||
didClickAggregationPageEntrance(): unknown;
|
||||
|
||||
getAggregationGroupModels(): unknown;
|
||||
|
||||
// {
|
||||
// "businessType": 1,
|
||||
// "uins": [
|
||||
// "1627126029",
|
||||
// "66600000",
|
||||
// "71702575"
|
||||
// ]
|
||||
// }
|
||||
|
||||
checkLikeStatus(param: {
|
||||
businessType: number,
|
||||
uins: string[]
|
||||
}): Promise<any>;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
15
src/core/src/services/NodeIKernelProfileLikeService.ts
Normal file
15
src/core/src/services/NodeIKernelProfileLikeService.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { BuddyProfileLikeReq } from "../entities/user";
|
||||
|
||||
export interface NodeIKernelProfileLikeService {
|
||||
addKernelProfileLikeListener(listener: NodeIKernelProfileLikeService): void;
|
||||
|
||||
removeKernelProfileLikeListener(listener: unknown): void;
|
||||
|
||||
setBuddyProfileLike(...args: unknown[]): { result: number, errMsg: string, succCounts: number };
|
||||
|
||||
getBuddyProfileLike(req: BuddyProfileLikeReq): void;
|
||||
|
||||
getProfileLikeScidResourceInfo(...args: unknown[]): void;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
77
src/core/src/services/NodeIKernelProfileService.ts
Normal file
77
src/core/src/services/NodeIKernelProfileService.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { AnyCnameRecord } from 'node:dns';
|
||||
import { BizKey, ModifyProfileParams, UserDetailInfoByUin } from '../entities';
|
||||
import { NodeIKernelProfileListener } from '../listeners';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
|
||||
export interface NodeIKernelProfileService {
|
||||
|
||||
addKernelProfileListener(listener: NodeIKernelProfileListener): number;
|
||||
|
||||
removeKernelProfileListener(listenerId: number): void;
|
||||
|
||||
prepareRegionConfig(...args: unknown[]): unknown;
|
||||
|
||||
getLocalStrangerRemark(): Promise<AnyCnameRecord>;
|
||||
|
||||
enumCountryOptions(): Array<string>;
|
||||
|
||||
enumProvinceOptions(Country: string): Array<string>;
|
||||
|
||||
enumCityOptions(Country: string, Province: string): unknown;
|
||||
|
||||
enumAreaOptions(...args: unknown[]): unknown;
|
||||
|
||||
//SimpleInfo
|
||||
// this.uid = "";
|
||||
// this.uid = str;
|
||||
// this.uin = j2;
|
||||
// this.isBuddy = z;
|
||||
// this.coreInfo = coreInfo;
|
||||
// this.baseInfo = baseInfo;
|
||||
// this.status = statusInfo;
|
||||
// this.vasInfo = vasInfo;
|
||||
// this.relationFlags = relationFlag;
|
||||
// this.otherFlags = otherFlag;
|
||||
// this.intimate = intimate;
|
||||
|
||||
modifySelfProfile(...args: unknown[]): Promise<unknown>;
|
||||
|
||||
modifyDesktopMiniProfile(param: ModifyProfileParams): Promise<GeneralCallResult>;
|
||||
|
||||
setNickName(NickName: string): Promise<unknown>;
|
||||
|
||||
setLongNick(longNick: string): Promise<unknown>;
|
||||
|
||||
setBirthday(...args: unknown[]): Promise<unknown>;
|
||||
|
||||
setGander(...args: unknown[]): Promise<unknown>;
|
||||
|
||||
setHeader(arg: string): Promise<unknown>;
|
||||
|
||||
setRecommendImgFlag(...args: unknown[]): Promise<unknown>;
|
||||
|
||||
getUserSimpleInfo(force: boolean, uids: string[],): Promise<unknown>;
|
||||
|
||||
getUserDetailInfo(uid: string): Promise<unknown>;
|
||||
|
||||
getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>;
|
||||
|
||||
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUin>;
|
||||
|
||||
getZplanAvatarInfos(args: string[]): Promise<unknown>;
|
||||
|
||||
getStatus(uid: string): Promise<unknown>;
|
||||
|
||||
startStatusPolling(isForceReset: boolean): Promise<unknown>;
|
||||
|
||||
getSelfStatus(): Promise<unknown>;
|
||||
//
|
||||
setdisableEmojiShortCuts(...args: unknown[]): unknown;
|
||||
|
||||
getProfileQzonePicInfo(uid: string, type: number, force: boolean): Promise<unknown>;
|
||||
|
||||
//profileService.getCoreInfo("UserRemarkServiceImpl::getStrangerRemarkByUid", arrayList);
|
||||
getCoreInfo(name: string, arg: any[]): unknown;
|
||||
//m429253e12.getOtherFlag("FriendListInfoCache_getKernelDataAndPutCache", new ArrayList<>());
|
||||
isNull(): boolean;
|
||||
}
|
||||
63
src/core/src/services/NodeIKernelRecentContactService.ts
Normal file
63
src/core/src/services/NodeIKernelRecentContactService.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Peer } from "../entities";
|
||||
|
||||
export interface NodeIKernelRecentContactService {
|
||||
setGuildDisplayStatus(...args: unknown[]): unknown; // 2 arguments
|
||||
|
||||
setContactListTop(...args: unknown[]): unknown; // 2 arguments
|
||||
|
||||
updateRecentContactExtBufForUI(...args: unknown[]): unknown; // 2 arguments
|
||||
|
||||
upsertRecentContactManually(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
enterOrExitMsgList(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
getRecentContactListSnapShot(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
clearMsgUnreadCount(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
getRecentContactListSyncLimit(count: number): unknown;
|
||||
|
||||
jumpToSpecifyRecentContact(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
fetchAndSubscribeABatchOfRecentContact(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
addRecentContact(peer: Peer): unknown;
|
||||
|
||||
deleteRecentContacts(peer: Peer): unknown; // 猜测
|
||||
|
||||
getContacts(peers: Peer[]): Promise<unknown>;
|
||||
|
||||
setThirdPartyBusinessInfos(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
updateGameMsgConfigs(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
removeKernelRecentContactListener(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
addKernelRecentContactListener(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
clearRecentContactsByChatType(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
upInsertModule(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
jumpToSpecifyRecentContactVer2(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
deleteRecentContactsVer2(...args: unknown[]): unknown; // 1 arguments
|
||||
|
||||
getRecentContactList(): unknown;
|
||||
|
||||
getMsgUnreadCount(): unknown;
|
||||
|
||||
clearRecentContacts(): unknown;
|
||||
|
||||
getServiceAssistantRecentContactInfos(): unknown;
|
||||
|
||||
getRecentContactInfos(): unknown;
|
||||
|
||||
getUnreadDetailsInfos(): unknown;
|
||||
|
||||
cleanAllModule(): unknown;
|
||||
|
||||
setAllGameMsgRead(): unknown;
|
||||
|
||||
getRecentContactListSync(): unknown;
|
||||
}
|
||||
170
src/core/src/services/NodeIKernelRichMediaService.ts
Normal file
170
src/core/src/services/NodeIKernelRichMediaService.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
import { GetFileListParam, Peer } from "../entities";
|
||||
import { GeneralCallResult } from "./common";
|
||||
|
||||
export interface NodeIKernelRichMediaService {
|
||||
//getVideoPlayUrl(peer, msgId, elemId, videoCodecFormat, VideoRequestWay.KHAND, cb);
|
||||
// public enum VideoCodecFormatType {
|
||||
// KCODECFORMATH264,
|
||||
// KCODECFORMATH265,
|
||||
// KCODECFORMATH266,
|
||||
// KCODECFORMATAV1
|
||||
// }
|
||||
// public enum VideoRequestWay {
|
||||
// KUNKNOW,
|
||||
// KHAND,
|
||||
// KAUTO
|
||||
// }
|
||||
getVideoPlayUrl(peer: Peer, msgId: string, elemId: string, videoCodecFormat: number, VideoRequestWay: number): Promise<unknown>;
|
||||
|
||||
//exParams (RMReqExParams)
|
||||
// this.downSourceType = i2;
|
||||
// this.triggerType = i3;
|
||||
//peer, msgId, elemId, videoCodecFormat, exParams
|
||||
// 1 0 频道在用
|
||||
// 1 1
|
||||
// 0 2
|
||||
|
||||
// public static final int KCOMMONREDENVELOPEMSGTYPEINMSGBOX = 1007;
|
||||
// public static final int KDOWNSOURCETYPEAIOINNER = 1;
|
||||
// public static final int KDOWNSOURCETYPEBIGSCREEN = 2;
|
||||
// public static final int KDOWNSOURCETYPEHISTORY = 3;
|
||||
// public static final int KDOWNSOURCETYPEUNKNOWN = 0;
|
||||
|
||||
// public static final int KTRIGGERTYPEAUTO = 1;
|
||||
// public static final int KTRIGGERTYPEMANUAL = 0;
|
||||
|
||||
getVideoPlayUrlV2(peer: Peer, msgId: string, elemId: string, videoCodecFormat: number, exParams: { downSourceType: number, triggerType: number }): Promise<GeneralCallResult & {
|
||||
urlResult: {
|
||||
v4IpUrl: [],
|
||||
v6IpUrl: [],
|
||||
domainUrl: Array<{
|
||||
url: string,
|
||||
isHttps: boolean,
|
||||
httpsDomain: string
|
||||
}>,
|
||||
videoCodecFormat: number
|
||||
}
|
||||
}>;
|
||||
|
||||
getRichMediaFileDir(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
// this.senderUid = "";
|
||||
// this.peerUid = "";
|
||||
// this.guildId = "";
|
||||
// this.elem = new MsgElement();
|
||||
// this.downloadType = i2;
|
||||
// this.thumbSize = i3;
|
||||
// this.msgId = j2;
|
||||
// this.msgRandom = j3;
|
||||
// this.msgSeq = j4;
|
||||
// this.msgTime = j5;
|
||||
// this.chatType = i4;
|
||||
// this.senderUid = str;
|
||||
// this.peerUid = str2;
|
||||
// this.guildId = str3;
|
||||
// this.elem = msgElement;
|
||||
// this.useHttps = num;
|
||||
|
||||
getVideoPlayUrlInVisit(arg: unknown): unknown;
|
||||
|
||||
isFileExpired(arg: unknown): unknown;
|
||||
|
||||
deleteGroupFolder(GroupCode: string, FolderId: string): Promise<GeneralCallResult & { groupFileCommonResult: { retCode: number, retMsg: string, clientWording: string } }>;
|
||||
|
||||
//参数与getVideoPlayUrlInVisit一样
|
||||
downloadRichMediaInVisit(arg: unknown): unknown;
|
||||
|
||||
downloadFileForModelId(peer: Peer, arg: unknown[], arg3: string): unknown;
|
||||
//第三个参数 Array<Type>
|
||||
// this.fileId = "";
|
||||
// this.fileName = "";
|
||||
// this.fileId = str;
|
||||
// this.fileName = str2;
|
||||
// this.fileSize = j2;
|
||||
// this.fileModelId = j3;
|
||||
|
||||
downloadFileForFileUuid(peer: Peer, arg1: string, arg3: unknown[]): unknown;
|
||||
|
||||
downloadFileByUrlListtransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
downloadFileForFileInfotransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
createGroupFolder(GroupCode: string, FolderName: string): Promise<GeneralCallResult & { resultWithGroupItem: { result: any, groupItem: Array<any> } }>
|
||||
|
||||
downloadFile(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown): unknown;
|
||||
|
||||
createGroupFoldertransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
downloadGroupFolder(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
renameGroupFolder(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
deleteGroupFoldertransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
deleteTransferInfotransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
cancelTransferTask(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
cancelUrlDownload(arg: unknown): unknown;
|
||||
|
||||
updateOnlineVideoElemStatus(arg: unknown): unknown;
|
||||
|
||||
getGroupSpace(arg: unknown): unknown;
|
||||
|
||||
getGroupFileList(groupCode: string, params: GetFileListParam): Promise<GeneralCallResult & {
|
||||
groupSpaceResult: {
|
||||
retCode: number
|
||||
retMsg: string
|
||||
clientWording: string
|
||||
totalSpace: number
|
||||
usedSpace: number
|
||||
allUpload: boolean
|
||||
}
|
||||
}>;
|
||||
|
||||
getGroupFileInfotransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
getGroupFileListtransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
getGroupTransferListtransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
renameGroupFile(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown, arg5: unknown): unknown;
|
||||
|
||||
moveGroupFile(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown, arg5: unknown): unknown;
|
||||
|
||||
transGroupFile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
searchGroupFileByWord(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown, arg5: unknown): unknown;
|
||||
|
||||
deleteGroupFile(GroupCode: string, params: Array<number>, Files: Array<string>): Promise<GeneralCallResult & {
|
||||
transGroupFileResult: {
|
||||
result: any
|
||||
successFileIdList: Array<any>
|
||||
failFileIdList: Array<any>
|
||||
}
|
||||
}>;
|
||||
|
||||
translateEnWordToZn(words: string[]): Promise<GeneralCallResult & { words: string[] }>;
|
||||
|
||||
getScreenOCR(path: string): Promise<unknown>;
|
||||
|
||||
batchGetGroupFileCount(Gids: Array<string>): Promise<GeneralCallResult & { groupCodes: Array<string>, groupFileCounts: Array<number> }>;
|
||||
|
||||
queryPicDownloadSize(arg: unknown): unknown;
|
||||
|
||||
searchGroupFiletransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
searchMoreGroupFile(arg: unknown): unknown;
|
||||
|
||||
cancelSearcheGroupFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
onlyDownloadFile(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
onlyUploadFiletransgroupfile(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
isExtraLargePic(arg1: unknown, arg2: unknown, arg3: unknown): unknown;
|
||||
|
||||
uploadRMFileWithoutMsg(arg: unknown): unknown;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
34
src/core/src/services/NodeIKernelRobotService.ts
Normal file
34
src/core/src/services/NodeIKernelRobotService.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { NodeIKernelRobotListener } from "@/core/listeners";
|
||||
|
||||
export interface NodeIKernelRobotService {
|
||||
fetchGroupRobotStoreDiscovery(arg: unknown): unknown;
|
||||
|
||||
sendGroupRobotStoreSearch(arg: unknown): unknown;
|
||||
|
||||
fetchGroupRobotStoreCategoryList(arg: unknown): unknown;
|
||||
|
||||
FetchSubscribeMsgTemplate(arg: unknown): unknown;
|
||||
|
||||
FetchSubcribeMsgTemplateStatus(arg: unknown): unknown;
|
||||
|
||||
SubscribeMsgTemplateSet(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
fetchRecentUsedRobots(arg: unknown): unknown;
|
||||
|
||||
fetchShareArkInfo(arg: unknown): unknown;
|
||||
|
||||
addKernelRobotListener(Listener: NodeIKernelRobotListener): number;
|
||||
|
||||
removeKernelRobotListener(ListenerId: number): unknown;
|
||||
|
||||
getAllRobotFriendsFromCache(): unknown;
|
||||
|
||||
fetchAllRobots(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
removeAllRecommendCache(): unknown;
|
||||
|
||||
setRobotPickTts(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
getRobotUinRange(data: any): Promise<{ response: { robotUinRanges: any } }>
|
||||
isNull(): boolean;
|
||||
}
|
||||
79
src/core/src/services/NodeIKernelSearchService.ts
Normal file
79
src/core/src/services/NodeIKernelSearchService.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
export interface NodeIKernelSearchService{
|
||||
addKernelSearchListenerr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
removeKernelSearchListenerr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
searchStrangerr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchGroupr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
searchLocalInfor(...args: any[]): unknown;// needs 2 arguments
|
||||
|
||||
cancelSearchLocalInfor(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchBuddyChatInfor(...args: any[]): unknown;// needs 2 arguments
|
||||
|
||||
searchMoreBuddyChatInfor(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchBuddyChatInfor(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchContactr(...args: any[]): unknown;// needs 2 arguments
|
||||
|
||||
searchMoreContactr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchContactr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchGroupChatInfor(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
resetSearchGroupChatInfoSortTyper(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
resetSearchGroupChatInfoFilterMembersr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchMoreGroupChatInfor(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchGroupChatInfor(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchChatsWithKeywordsr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchMoreChatsWithKeywordsr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchChatsWithKeywordsr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchChatMsgsr(...args: any[]): unknown;// needs 2 arguments
|
||||
|
||||
searchMoreChatMsgsr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchChatMsgsr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchMsgWithKeywordsr(...args: any[]): unknown;// needs 2 arguments
|
||||
|
||||
searchMoreMsgWithKeywordsr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchMsgWithKeywordsr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchFileWithKeywordsr(...args: any[]): unknown;// needs 2 arguments
|
||||
|
||||
searchMoreFileWithKeywordsr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchFileWithKeywordsr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchAtMeChatsr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchMoreAtMeChatsr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchAtMeChatsr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
searchChatAtMeMsgsr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
searchMoreChatAtMeMsgsr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
cancelSearchChatAtMeMsgsr(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
addSearchHistoryr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
removeSearchHistoryr(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
searchCacher(...args: any[]): unknown;// needs 3 arguments
|
||||
|
||||
clearSearchCacher(...args: any[]): unknown;// needs 1 arguments
|
||||
}
|
||||
41
src/core/src/services/NodeIKernelStorageCleanService.ts
Normal file
41
src/core/src/services/NodeIKernelStorageCleanService.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { NodeIKernelStorageCleanListener } from "@/core/listeners";
|
||||
import { GeneralCallResult } from "./common";
|
||||
|
||||
export interface NodeIKernelStorageCleanService {
|
||||
|
||||
addKernelStorageCleanListener(Listener: NodeIKernelStorageCleanListener): number;
|
||||
|
||||
removeKernelStorageCleanListener(ListenerId: number): void;
|
||||
|
||||
addCacheScanedPaths(arg: unknown): unknown;
|
||||
|
||||
addFilesScanedPaths(arg: unknown): unknown;
|
||||
|
||||
scanCache(): Promise<GeneralCallResult & {
|
||||
size: string[]
|
||||
}>;
|
||||
|
||||
addReportData(arg: unknown): unknown;
|
||||
|
||||
reportData(): unknown;
|
||||
|
||||
getChatCacheInfo(arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown): unknown;
|
||||
|
||||
getFileCacheInfo(arg1: unknown, arg2: unknown, arg3: unknown, arg44: unknown, args5: unknown): unknown;
|
||||
|
||||
clearChatCacheInfo(arg1: unknown, arg2: unknown): unknown;
|
||||
|
||||
clearCacheDataByKeys(arg: unknown): unknown;
|
||||
|
||||
setSilentScan(arg: unknown): unknown;
|
||||
|
||||
closeCleanWindow(): unknown;
|
||||
|
||||
clearAllChatCacheInfo(): unknown;
|
||||
|
||||
endScan(arg: unknown): unknown;
|
||||
|
||||
addNewDownloadOrUploadFile(arg: unknown): unknown;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
10
src/core/src/services/NodeIKernelTianShuService.ts
Normal file
10
src/core/src/services/NodeIKernelTianShuService.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export interface NodeIKernelTianShuService {
|
||||
addKernelTianShuListener(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
removeKernelTianShuListener(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
requesTianShuNumeralRe(...args: any[]): unknown;//d needs 1 arguments
|
||||
|
||||
reportTianShuNumeralRed(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
}
|
||||
12
src/core/src/services/NodeIKernelTicketService.ts
Normal file
12
src/core/src/services/NodeIKernelTicketService.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { forceFetchClientKeyRetType } from "./common";
|
||||
|
||||
export interface NodeIKernelTicketService {
|
||||
|
||||
addKernelTicketListener(listener: unknown): void;
|
||||
|
||||
removeKernelTicketListener(listenerId: unknown): void;
|
||||
|
||||
forceFetchClientKey(arg: string): Promise<forceFetchClientKeyRetType>;
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
20
src/core/src/services/NodeIKernelTipOffService.ts
Normal file
20
src/core/src/services/NodeIKernelTipOffService.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { GeneralCallResult } from "./common";
|
||||
|
||||
export interface NodeIKernelTipOffService {
|
||||
|
||||
addKernelTipOffListener(listener: unknown): void;
|
||||
|
||||
removeKernelTipOffListener(listenerId: unknown): void;
|
||||
|
||||
tipOffSendJsData(args: unknown[]): Promise<unknown>;//2
|
||||
|
||||
getPskey(domainList: string[], nocache: boolean): Promise<GeneralCallResult & { domainPskeyMap: Map<string, string> }>;//2
|
||||
|
||||
tipOffSendJsData(args: unknown[]): Promise<unknown>;//2
|
||||
|
||||
tipOffMsgs(args: unknown[]): Promise<unknown>;//1
|
||||
|
||||
encodeUinAesInfo(args: unknown[]): Promise<unknown>;//2
|
||||
|
||||
isNull(): boolean;
|
||||
}
|
||||
5
src/core/src/services/NodeIKernelUixConvertService.ts
Normal file
5
src/core/src/services/NodeIKernelUixConvertService.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface NodeIKernelUixConvertService {
|
||||
getUin(uid: string[]): Promise<{ uidInfo: Map<string, string> }>;
|
||||
|
||||
getUid(uin: string[]): Promise<{ uinInfo: Map<string, string> }>;
|
||||
}
|
||||
15
src/core/src/services/NodeIKernelUnitedConfigService.ts
Normal file
15
src/core/src/services/NodeIKernelUnitedConfigService.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export interface NodeIKernelUnitedConfigService{
|
||||
addKernelUnitedConfigListener(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
removeKernelUnitedConfigListener(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
fetchUnitedCommendConfig(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
fetchUnitedSwitchConfig(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
loadUnitedConfig(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments
|
||||
|
||||
registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments
|
||||
}
|
||||
5
src/core/src/services/NodeIYellowFaceService.ts
Normal file
5
src/core/src/services/NodeIYellowFaceService.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// public interface IYellowFaceForManagerService extends QRouteApi {
|
||||
// void download(@NotNull String resourceConfigJson, @NotNull String resourceDir, @NotNull String cacheDir, boolean force, @NotNull IKernelYellowFaceDownloadCallback callback);
|
||||
|
||||
// void setHistory(@NotNull String fullMd5, @NotNull IOperateCallback callback);
|
||||
// }
|
||||
15
src/core/src/services/common.ts
Normal file
15
src/core/src/services/common.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
export enum GeneralCallResultStatus {
|
||||
OK = 0,
|
||||
// ERROR = 1,
|
||||
}
|
||||
export interface GeneralCallResult{
|
||||
result: GeneralCallResultStatus,
|
||||
errMsg: string
|
||||
}
|
||||
export interface forceFetchClientKeyRetType extends GeneralCallResult {
|
||||
url: string;
|
||||
keyIndex: string;
|
||||
clientKey: string;
|
||||
expireTime: string;
|
||||
}
|
||||
16
src/core/src/services/index.ts
Normal file
16
src/core/src/services/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export * from './common';
|
||||
export * from './NodeIKernelAvatarService';
|
||||
export * from './NodeIKernelBuddyService';
|
||||
export * from './NodeIKernelFileAssistantService';
|
||||
export * from './NodeIKernelGroupService';
|
||||
export * from './NodeIKernelLoginService';
|
||||
export * from './NodeIKernelMsgService';
|
||||
export * from './NodeIKernelOnlineStatusService';
|
||||
export * from './NodeIKernelProfileLikeService';
|
||||
export * from './NodeIKernelProfileService';
|
||||
export * from './NodeIKernelTicketService';
|
||||
export * from './NodeIKernelStorageCleanService';
|
||||
export * from './NodeIKernelRobotService';
|
||||
export * from './NodeIKernelRichMediaService';
|
||||
export * from './NodeIKernelDbToolsService';
|
||||
export * from './NodeIKernelTipOffService'
|
||||
131
src/core/src/sessionConfig.ts
Normal file
131
src/core/src/sessionConfig.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { appid, qqPkgInfo, qqVersionConfigInfo } from '@/common/utils/QQBasicInfo';
|
||||
import { hostname, systemName, systemVersion } from '@/common/utils/system';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import { getMachineId } from '@/common/utils/system';
|
||||
// 补充
|
||||
export enum PlatformType {
|
||||
KUNKNOWN,
|
||||
KANDROID,
|
||||
KIOS,
|
||||
KWINDOWS,
|
||||
KMAC
|
||||
}
|
||||
export enum DeviceType {
|
||||
KUNKNOWN,
|
||||
KPHONE,
|
||||
KPAD,
|
||||
KCOMPUTER
|
||||
}
|
||||
//推送类型
|
||||
export enum VendorType {
|
||||
KNOSETONIOS = 0,
|
||||
KSUPPORTGOOGLEPUSH = 99,
|
||||
KSUPPORTHMS = 3,
|
||||
KSUPPORTOPPOPUSH = 4,
|
||||
KSUPPORTTPNS = 2,
|
||||
KSUPPORTVIVOPUSH = 5,
|
||||
KUNSUPPORTANDROIDPUSH = 1
|
||||
}
|
||||
export interface WrapperSessionInitConfig {
|
||||
selfUin: string
|
||||
selfUid: string
|
||||
desktopPathConfig: {
|
||||
account_path: string // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
||||
}
|
||||
clientVer: string // 9.9.8-22355
|
||||
a2: '',
|
||||
d2: '',
|
||||
d2Key: '',
|
||||
machineId: '',
|
||||
platform: 3, // 3是Windows?
|
||||
platVer: string, // 系统版本号, 应该可以固定
|
||||
appid: string,
|
||||
rdeliveryConfig: {
|
||||
appKey: '',
|
||||
systemId: 0,
|
||||
appId: '',
|
||||
logicEnvironment: '',
|
||||
platform: 3,
|
||||
language: '',
|
||||
sdkVersion: '',
|
||||
userId: '',
|
||||
appVersion: '',
|
||||
osVersion: '',
|
||||
bundleId: '',
|
||||
serverUrl: '',
|
||||
fixedAfterHitKeys: ['']
|
||||
}
|
||||
'defaultFileDownloadPath': string, // 这个可以通过环境变量获取?
|
||||
'deviceInfo': {
|
||||
'guid': string,
|
||||
'buildVer': string,
|
||||
'localId': 2052,
|
||||
'devName': string,
|
||||
'devType': string,
|
||||
'vendorName': '',
|
||||
'osVer': string,
|
||||
'vendorOsName': string,
|
||||
'setMute': false,
|
||||
'vendorType': 0
|
||||
},
|
||||
'deviceConfig': '{"appearance":{"isSplitViewMode":true},"msg":{}}'
|
||||
}
|
||||
|
||||
export const sessionConfig: WrapperSessionInitConfig | any = {};
|
||||
|
||||
export async function genSessionConfig(selfUin: string, selfUid: string, account_path: string): Promise<WrapperSessionInitConfig> {
|
||||
const downloadPath = path.join(account_path, 'NapCat', 'temp');
|
||||
fs.mkdirSync(downloadPath, { recursive: true });
|
||||
let guid: string = await getMachineId();
|
||||
//console.log(guid);
|
||||
// guid = '52afb776-82f6-4e59-9d38-44705b112d0a';
|
||||
//let guid: string = await getMachineId();
|
||||
const config: WrapperSessionInitConfig = {
|
||||
selfUin,
|
||||
selfUid,
|
||||
desktopPathConfig: {
|
||||
account_path // 可以通过NodeQQNTWrapperUtil().getNTUserDataInfoConfig()获取
|
||||
},
|
||||
clientVer: qqVersionConfigInfo.curVersion, // 9.9.8-22355
|
||||
a2: '',
|
||||
d2: '',
|
||||
d2Key: '',
|
||||
machineId: '',
|
||||
platform: 3, // 3是Windows?
|
||||
platVer: systemVersion, // 系统版本号, 应该可以固定
|
||||
appid: appid,
|
||||
rdeliveryConfig: {
|
||||
appKey: '',
|
||||
systemId: 0,
|
||||
appId: '',
|
||||
logicEnvironment: '',
|
||||
platform: 3,
|
||||
language: '',
|
||||
sdkVersion: '',
|
||||
userId: '',
|
||||
appVersion: '',
|
||||
osVersion: '',
|
||||
bundleId: '',
|
||||
serverUrl: '',
|
||||
fixedAfterHitKeys: ['']
|
||||
},
|
||||
'defaultFileDownloadPath': downloadPath,
|
||||
'deviceInfo': {
|
||||
guid,
|
||||
'buildVer': qqPkgInfo.version,
|
||||
'localId': 2052,
|
||||
'devName': hostname,
|
||||
'devType': systemName,
|
||||
'vendorName': '',
|
||||
'osVer': systemVersion,
|
||||
'vendorOsName': systemName,
|
||||
'setMute': false,
|
||||
'vendorType': 0
|
||||
},
|
||||
'deviceConfig': '{"appearance":{"isSplitViewMode":true},"msg":{}}'
|
||||
};
|
||||
Object.assign(sessionConfig, config);
|
||||
// log(sessionConfig);
|
||||
return config;
|
||||
}
|
||||
30
src/core/src/utils/config.ts
Normal file
30
src/core/src/utils/config.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import { enableConsoleLog, enableFileLog, logDebug, logError, LogLevel, setLogLevel } from '@/common/utils/log';
|
||||
import { ConfigBase } from '@/common/utils/ConfigBase';
|
||||
import { selfInfo } from '@/core/data';
|
||||
|
||||
|
||||
export interface NapCatConfig {
|
||||
fileLog: boolean,
|
||||
consoleLog: boolean,
|
||||
fileLogLevel: LogLevel,
|
||||
consoleLogLevel: LogLevel,
|
||||
}
|
||||
|
||||
class Config extends ConfigBase<NapCatConfig> implements NapCatConfig{
|
||||
fileLog = true;
|
||||
consoleLog = true;
|
||||
fileLogLevel = LogLevel.DEBUG;
|
||||
consoleLogLevel = LogLevel.INFO;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
getConfigPath() {
|
||||
return path.join(this.getConfigDir(), `napcat_${selfInfo.uin}.json`);
|
||||
}
|
||||
}
|
||||
|
||||
export const napCatConfig = new Config();
|
||||
|
||||
42
src/core/src/utils/rkey.ts
Normal file
42
src/core/src/utils/rkey.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
//远端rkey获取
|
||||
import { logError } from '@/common/utils/log';
|
||||
import { RequestUtil } from '@/common/utils/request';
|
||||
|
||||
interface ServerRkeyData {
|
||||
group_rkey: string;
|
||||
private_rkey: string;
|
||||
expired_time: number;
|
||||
}
|
||||
|
||||
class RkeyManager {
|
||||
serverUrl: string = '';
|
||||
private rkeyData: ServerRkeyData = {
|
||||
group_rkey: '',
|
||||
private_rkey: '',
|
||||
expired_time: 0
|
||||
};
|
||||
constructor(serverUrl: string) {
|
||||
this.serverUrl = serverUrl;
|
||||
}
|
||||
async getRkey() {
|
||||
if (this.isExpired()) {
|
||||
try {
|
||||
await this.refreshRkey();
|
||||
} catch (e) {
|
||||
logError('获取rkey失败', e);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
async refreshRkey(): Promise<any> {
|
||||
//刷新rkey
|
||||
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(this.serverUrl, 'GET');
|
||||
}
|
||||
}
|
||||
export const rkeyManager = new RkeyManager('http://napcat-sign.wumiao.wang:2082/rkey');
|
||||
296
src/core/src/wrapper.ts
Normal file
296
src/core/src/wrapper.ts
Normal file
@@ -0,0 +1,296 @@
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import { WrapperSessionInitConfig } from './sessionConfig';
|
||||
import {
|
||||
NodeIDependsAdapter,
|
||||
NodeIDispatcherAdapter,
|
||||
NodeIGlobalAdapter,
|
||||
} from './adapters';
|
||||
import {
|
||||
NodeIKernelSessionListener,
|
||||
NodeIKernelMsgListener,
|
||||
NodeIKernelLoginListener,
|
||||
NodeIKernelBuddyListener,
|
||||
NodeIKernelGroupListener,
|
||||
NodeIKernelProfileListener,
|
||||
} from './listeners';
|
||||
import {
|
||||
NodeIKernelLoginService,
|
||||
NodeIKernelMsgService,
|
||||
NodeIKernelBuddyService,
|
||||
NodeIKernelGroupService,
|
||||
NodeIKernelProfileService,
|
||||
NodeIKernelProfileLikeService,
|
||||
NodeIKernelTicketService,
|
||||
NodeIKernelTipOffService,
|
||||
NodeIKernelRichMediaService,
|
||||
NodeIKernelAvatarService,
|
||||
} from './services';
|
||||
import { qqVersionConfigInfo } from '@/common/utils/QQBasicInfo';
|
||||
import { NodeIKernelStorageCleanService } from './services/NodeIKernelStorageCleanService';
|
||||
import { NodeIKernelRobotService } from './services/NodeIKernelRobotService';
|
||||
import { dirname } from "node:path"
|
||||
import { fileURLToPath } from "node:url"
|
||||
import { NodeIKernelNodeMiscService } from './services/NodeIKernelNodeMiscService';
|
||||
import { NodeIKernelUixConvertService } from './services/NodeIKernelUixConvertService';
|
||||
import { NodeIKernelMsgBackupService } from './services/NodeIKernelMsgBackupService';
|
||||
import { NodeIKernelAlbumService } from './services/NodeIKernelAlbumService';
|
||||
import { NodeIKernelTianShuService } from './services/NodeIKernelTianShuService';
|
||||
import { NodeIKernelUnitedConfigService } from './services/NodeIKernelUnitedConfigService';
|
||||
import { NodeIKernelSearchService } from './services/NodeIKernelSearchService';
|
||||
import { NodeIKernelCollectionService } from './services/NodeIKernelCollectionService';
|
||||
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
export interface NodeQQNTWrapperUtil {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(): NodeQQNTWrapperUtil
|
||||
|
||||
getNTUserDataInfoConfig(): string
|
||||
|
||||
emptyWorkingSet(n: number): void
|
||||
|
||||
getSsoCmdOfOidbReq(arg1: number, arg2: number): unknown,
|
||||
|
||||
getSsoBufferOfOidbReq(...args: unknown[]): unknown,//有点看不懂参数定义 待补充 好像是三个参数
|
||||
|
||||
getOidbRspInfo(arg: string): unknown,//可能是错的
|
||||
|
||||
getFileSize(path: string): Promise<number>,//直接的猜测
|
||||
|
||||
genFileMd5Buf(arg: string): unknown,//可能是错的
|
||||
|
||||
genFileMd5Hex(path: string): unknown,//直接的猜测
|
||||
|
||||
genFileShaBuf(path: string): unknown,//直接的猜测
|
||||
|
||||
genFileCumulateSha1(path: string): unknown,//直接的猜测
|
||||
|
||||
genFileShaHex(path: string): unknown,//直接的猜测
|
||||
|
||||
fileIsExist(path: string): unknown,
|
||||
|
||||
startTrace(path: string): unknown,//可能是错的
|
||||
|
||||
copyFile(src: string, dst: string): unknown,
|
||||
|
||||
genFileShaAndMd5Hex(path: string, unknown: number): unknown,//可能是错的
|
||||
|
||||
setTraceInfo(unknown: Object): unknown,
|
||||
|
||||
encodeOffLine(unknown: Object): unknown,
|
||||
|
||||
decodeOffLine(arg: string): unknown,//可能是错的 传递hex
|
||||
|
||||
DecoderRecentInfo(arg: string): unknown,//可能是错的 传递hex
|
||||
|
||||
getPinyin(arg0: string, arg1: boolean): unknown,
|
||||
|
||||
matchInPinyin(arg0: any[], arg1: string): unknown,//参数特复杂 arg0是个复杂数据类型
|
||||
|
||||
makeDirByPath(arg0: string): unknown,
|
||||
|
||||
emptyWorkingSet(arg0: number): unknown,//参数是UINT32
|
||||
|
||||
runProcess(arg0: string, arg1: boolean): unknown,
|
||||
|
||||
runProcessArgs(arg0: string, arg1: { [key: string]: string; }, arg2: boolean): unknown,
|
||||
|
||||
calcThumbSize(arg0: number, arg1: number, arg2: Object): unknown,
|
||||
|
||||
fullWordToHalfWord(arg0: string): unknown,
|
||||
|
||||
getNTUserDataInfoConfig(): unknown,
|
||||
|
||||
pathIsReadableAndWriteable(path: string): unknown,//直接的猜测
|
||||
|
||||
resetUserDataSavePathToDocument(): unknown,
|
||||
|
||||
getSoBuildInfo(): any,//例如 0[0]_d491dc01e0a_0
|
||||
|
||||
registerCountInstruments(arg0: string, arg1: string[], arg2: number, arg3: number): unknown,
|
||||
|
||||
registerValueInstruments(arg0: string, arg1: string[], arg2: number, arg3: number): unknown,
|
||||
|
||||
registerValueInstrumentsWithBoundary(arg0: string, arg1: unknown, arg2: unknown, arg3: number, arg4: number): unknown,
|
||||
|
||||
reportCountIndicators(arg0: string, arg1: Map<unknown, unknown>, arg2: string, arg3: number, arg4: boolean): unknown,
|
||||
|
||||
reportValueIndicators(arg0: string, arg1: Map<unknown, unknown>, arg2: string, arg3: boolean, arg4: number): unknown,
|
||||
|
||||
checkNewUserDataSaveDirAvailable(arg0: string): unknown,
|
||||
|
||||
copyUserData(arg0: string, arg1: string): Promise<any>,
|
||||
|
||||
setUserDataSaveDirectory(arg0: string): Promise<any>,
|
||||
|
||||
hasOtherRunningQQProcess(): boolean,
|
||||
|
||||
quitAllRunningQQProcess(arg: boolean): unknown,
|
||||
|
||||
checkNvidiaConfig(): unknown,
|
||||
|
||||
repairNvidiaConfig(): unknown,
|
||||
|
||||
getNvidiaDriverVersion(): unknown,
|
||||
|
||||
isNull(): unknown
|
||||
}
|
||||
|
||||
export interface NodeIQQNTWrapperSession {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(): NodeIQQNTWrapperSession;
|
||||
|
||||
init(
|
||||
wrapperSessionInitConfig: WrapperSessionInitConfig,
|
||||
nodeIDependsAdapter: NodeIDependsAdapter,
|
||||
nodeIDispatcherAdapter: NodeIDispatcherAdapter,
|
||||
nodeIKernelSessionListener: NodeIKernelSessionListener
|
||||
): void;
|
||||
|
||||
startNT(n: 0): void;
|
||||
|
||||
startNT(): void;
|
||||
|
||||
getMsgService(): NodeIKernelMsgService;
|
||||
|
||||
getProfileService(): NodeIKernelProfileService;
|
||||
|
||||
getProfileLikeService(): NodeIKernelProfileLikeService;
|
||||
|
||||
getGroupService(): NodeIKernelGroupService;
|
||||
|
||||
getStorageCleanService(): NodeIKernelStorageCleanService;
|
||||
|
||||
getBuddyService(): NodeIKernelBuddyService;
|
||||
|
||||
getRobotService(): NodeIKernelRobotService;
|
||||
|
||||
getTicketService(): NodeIKernelTicketService;
|
||||
|
||||
getTipOffService(): NodeIKernelTipOffService;
|
||||
|
||||
getNodeMiscService(): NodeIKernelNodeMiscService;
|
||||
|
||||
getRichMediaService(): NodeIKernelRichMediaService;
|
||||
|
||||
getMsgBackupService(): NodeIKernelMsgBackupService;
|
||||
|
||||
getAlbumService(): NodeIKernelAlbumService;
|
||||
|
||||
getTianShuService(): NodeIKernelTianShuService;
|
||||
|
||||
getUnitedConfigService(): NodeIKernelUnitedConfigService;
|
||||
|
||||
getSearchService(): NodeIKernelSearchService;
|
||||
|
||||
getDirectSessionService(): unknown;
|
||||
|
||||
getRDeliveryService(): unknown;
|
||||
|
||||
getAvatarService(): NodeIKernelAvatarService;
|
||||
|
||||
getFeedChannelService(): unknown;
|
||||
|
||||
getYellowFaceService(): unknown;
|
||||
|
||||
getCollectionService(): NodeIKernelCollectionService;
|
||||
|
||||
getSettingService(): unknown;
|
||||
|
||||
getQiDianService(): unknown;
|
||||
|
||||
getFileAssistantService(): unknown;
|
||||
|
||||
getGuildService(): unknown;
|
||||
|
||||
getSkinService(): unknown;
|
||||
|
||||
getTestPerformanceService(): unknown;
|
||||
|
||||
getQQPlayService(): unknown;
|
||||
|
||||
getDbToolsService(): unknown;
|
||||
|
||||
getUixConvertService(): NodeIKernelUixConvertService;
|
||||
|
||||
getOnlineStatusService(): unknown;
|
||||
|
||||
getRemotingService(): unknown;
|
||||
|
||||
getGroupTabService(): unknown;
|
||||
|
||||
getGroupSchoolService(): unknown;
|
||||
|
||||
getLiteBusinessService(): unknown;
|
||||
|
||||
getGuildMsgService(): unknown;
|
||||
|
||||
getLockService(): unknown;
|
||||
|
||||
getMSFService(): unknown
|
||||
|
||||
getGuildHotUpdateService(): unknown;
|
||||
|
||||
getAVSDKService(): unknown;
|
||||
|
||||
getRecentContactService(): unknown;
|
||||
|
||||
getConfigMgrService(): unknown;
|
||||
}
|
||||
|
||||
export interface EnginInitDesktopConfig {
|
||||
base_path_prefix: string,
|
||||
platform_type: 3,
|
||||
app_type: 4,
|
||||
app_version: string,
|
||||
os_version: string,
|
||||
use_xlog: true,
|
||||
qua: string,
|
||||
global_path_config: {
|
||||
desktopGlobalPath: string,
|
||||
},
|
||||
thumb_config: { maxSide: 324, minSide: 48, longLimit: 6, density: 2 }
|
||||
}
|
||||
|
||||
export interface NodeIQQNTWrapperEngine {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(): NodeIQQNTWrapperEngine;
|
||||
|
||||
initWithDeskTopConfig(config: EnginInitDesktopConfig, nodeIGlobalAdapter: NodeIGlobalAdapter): void;
|
||||
}
|
||||
|
||||
export interface WrapperNodeApi {
|
||||
[key: string]: any;
|
||||
|
||||
NodeIKernelBuddyListener: NodeIKernelBuddyListener;
|
||||
NodeIKernelGroupListener: NodeIKernelGroupListener;
|
||||
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
||||
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
||||
NodeIKernelMsgListener: NodeIKernelMsgListener;
|
||||
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
||||
NodeIGlobalAdapter: NodeIGlobalAdapter;
|
||||
NodeIDependsAdapter: NodeIDependsAdapter;
|
||||
NodeIDispatcherAdapter: NodeIDispatcherAdapter;
|
||||
NodeIKernelSessionListener: NodeIKernelSessionListener;
|
||||
NodeIKernelLoginService: NodeIKernelLoginService;
|
||||
NodeIKernelLoginListener: NodeIKernelLoginListener;
|
||||
|
||||
NodeIKernelProfileService: NodeIKernelProfileService;
|
||||
NodeIKernelProfileListener: NodeIKernelProfileListener;
|
||||
}
|
||||
|
||||
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/${qqVersionConfigInfo.curVersion}/wrapper.node`);
|
||||
}
|
||||
let WrapperLoader = path.join(__dirname, "WrapperLoader.cjs");
|
||||
//此处待优化
|
||||
fs.writeFileSync(WrapperLoader, `
|
||||
module.exports = require("${wrapperNodePath.replace(/\\/g, "\\\\")}");
|
||||
exports = module.exports;
|
||||
`)
|
||||
const QQWrapper: WrapperNodeApi = (await import("file://" + WrapperLoader)).default;
|
||||
export default QQWrapper;
|
||||
43
src/core/tsconfig.json
Normal file
43
src/core/tsconfig.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": "./dist",
|
||||
"declaration": true,
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "ESNext",
|
||||
"lib": [
|
||||
"ES2020",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "Node",
|
||||
"experimentalDecorators": true,
|
||||
"allowImportingTsExtensions": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": false,
|
||||
"jsx": "preserve",
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"@/common/*": [
|
||||
"../common/*"
|
||||
],
|
||||
"@/core": [
|
||||
"./src/index"
|
||||
],
|
||||
"@/core/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*.ts"
|
||||
]
|
||||
}
|
||||
116
src/core/vite.config.ts
Normal file
116
src/core/vite.config.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { UserConfig, defineConfig } from 'vite';
|
||||
import { builtinModules } from 'module';
|
||||
import obfuscator from 'rollup-plugin-obfuscator';
|
||||
import { Plugin } from 'vite';
|
||||
import path from 'node:path';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import cp from 'vite-plugin-cp';
|
||||
import babel from 'vite-plugin-babel';
|
||||
|
||||
const external: string[] = [ /* Empty */];
|
||||
const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat();
|
||||
|
||||
const baseConfig: UserConfig = {
|
||||
build: {
|
||||
target: 'modules',
|
||||
outDir: './',
|
||||
lib: {
|
||||
name: '@napneko/core',
|
||||
entry: 'src/index.ts',
|
||||
formats: ['es'],
|
||||
fileName: () => 'index.js',
|
||||
},
|
||||
rollupOptions: {
|
||||
input: {
|
||||
index: path.resolve(__dirname, 'src/index.ts'),
|
||||
qqnt: path.resolve(__dirname, 'src/qqnt/index.ts'),
|
||||
'qqnt/apis': path.resolve(__dirname, 'src/qqnt/apis/index.ts'),
|
||||
'qqnt/listeners': path.resolve(__dirname, 'src/qqnt/listeners/index.ts'),
|
||||
'qqnt/entities': path.resolve(__dirname, 'src/qqnt/entities/index.ts'),
|
||||
'qqnt/adapters': path.resolve(__dirname, 'src/qqnt/adapters/index.ts'),
|
||||
'qqnt/services': path.resolve(__dirname, 'src/qqnt/services/index.ts'),
|
||||
service: path.resolve(__dirname, 'src/service/index.ts')
|
||||
},
|
||||
output: {
|
||||
// 输出设置为系统模块格式,确保目录结构被保持
|
||||
format: 'esm',
|
||||
dir: path.resolve(__dirname, './dist/core/src'),
|
||||
entryFileNames: '[name]/index.js',
|
||||
chunkFileNames: '[name]/[hash]/index.js',
|
||||
// preserveModules: true, // 保持模块结构
|
||||
// preserveModulesRoot: 'src'
|
||||
},
|
||||
external: [...nodeModules, ...external],
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@/common': path.resolve(__dirname, '../common'),
|
||||
'@/core': path.resolve(__dirname, './src'),
|
||||
'./lib-cov/fluent-ffmpeg': './lib/fluent-ffmpeg',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const commonPlugins: Plugin[] = [
|
||||
babel({
|
||||
filter: /.*\.(ts)$/,
|
||||
babelConfig: {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
presets: ["@babel/preset-typescript"],
|
||||
plugins: [
|
||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
],
|
||||
},
|
||||
}),
|
||||
dts({
|
||||
outDir: './dist',
|
||||
staticImport: true,
|
||||
rollupTypes: false,
|
||||
include: 'src/**/*.ts',
|
||||
}),
|
||||
cp({
|
||||
targets: [
|
||||
// ...external.map(genCpModule),
|
||||
{ src: './pub-package.json', dest: '../core.lib', rename: 'package.json' },
|
||||
]
|
||||
})
|
||||
];
|
||||
export default defineConfig(({ mode }) => {
|
||||
const result: UserConfig = { ...baseConfig };
|
||||
if (mode === 'production') {
|
||||
result.build!.minify = 'esbuild';
|
||||
result.plugins = [
|
||||
obfuscator({
|
||||
options: {
|
||||
compact: true,
|
||||
controlFlowFlattening: true,
|
||||
controlFlowFlatteningThreshold: 0.75,
|
||||
deadCodeInjection: true,
|
||||
deadCodeInjectionThreshold: 0.4,
|
||||
debugProtection: false,
|
||||
disableConsoleOutput: false,
|
||||
identifierNamesGenerator: 'hexadecimal',
|
||||
log: false,
|
||||
renameGlobals: false,
|
||||
rotateStringArray: true,
|
||||
selfDefending: true,
|
||||
stringArray: true,
|
||||
stringArrayEncoding: ['base64'],
|
||||
stringArrayThreshold: 0.75,
|
||||
transformObjectKeys: true,
|
||||
unicodeEscapeSequence: false
|
||||
},
|
||||
include: ['src/**/*.js', 'src/**/*.ts'],
|
||||
}),
|
||||
...commonPlugins
|
||||
];
|
||||
} else {
|
||||
result.build!.minify = false;
|
||||
result.plugins = [...commonPlugins];
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
Reference in New Issue
Block a user