mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
@@ -12,7 +12,7 @@ insert_final_newline = true
|
||||
# Set default charset
|
||||
charset = utf-8
|
||||
|
||||
# 2 space indentation
|
||||
# 4 space indentation
|
||||
[*.{cjs,mjs,js,jsx,ts,tsx,css,scss,sass,html,json}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
@@ -1,70 +1,32 @@
|
||||
import typescriptEslint from "@typescript-eslint/eslint-plugin";
|
||||
import _import from "eslint-plugin-import";
|
||||
import { fixupPluginRules } from "@eslint/compat";
|
||||
import eslint from '@eslint/js';
|
||||
import tsEslintPlugin from '@typescript-eslint/eslint-plugin';
|
||||
import tsEslintParser from '@typescript-eslint/parser';
|
||||
import globals from "globals";
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import js from "@eslint/js";
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
|
||||
const filename = fileURLToPath(import.meta.url);
|
||||
const dirname = path.dirname(filename);
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
});
|
||||
|
||||
export default [{
|
||||
ignores: ["src/core/proto/"],
|
||||
}, ...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"), {
|
||||
plugins: {
|
||||
"@typescript-eslint": typescriptEslint,
|
||||
import: fixupPluginRules(_import),
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
|
||||
settings: {
|
||||
"import/parsers": {
|
||||
"@typescript-eslint/parser": [".ts"],
|
||||
},
|
||||
|
||||
"import/resolver": {
|
||||
typescript: {
|
||||
alwaysTryTypes: true,
|
||||
const customTsFlatConfig = [
|
||||
{
|
||||
name: 'typescript-eslint/base',
|
||||
languageOptions: {
|
||||
parser: tsEslintParser,
|
||||
sourceType: 'module',
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
NodeJS: 'readonly', // 添加 NodeJS 全局变量
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
rules: {
|
||||
indent: ["error", 4],
|
||||
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"],
|
||||
},
|
||||
}, {
|
||||
files: ["**/.eslintrc.{js,cjs}"],
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
rules: {
|
||||
...tsEslintPlugin.configs.recommended.rules,
|
||||
'quotes': ['error', 'single'], // 使用单引号
|
||||
'semi': ['error', 'always'], // 强制使用分号
|
||||
'indent': ['error', 4], // 使用 4 空格缩进
|
||||
},
|
||||
ecmaVersion: 5,
|
||||
sourceType: "commonjs",
|
||||
plugins: {
|
||||
'@typescript-eslint': tsEslintPlugin,
|
||||
},
|
||||
ignores: ['src/webui/**'], // 忽略 src/webui/ 目录所有文件
|
||||
},
|
||||
}];
|
||||
];
|
||||
|
||||
export default [eslint.configs.recommended, ...customTsFlatConfig];
|
2
napcat.webui/src/types/user.d.ts
vendored
2
napcat.webui/src/types/user.d.ts
vendored
@@ -164,7 +164,7 @@ interface CommonExt {
|
||||
address: string
|
||||
regTime: number
|
||||
interest: string
|
||||
labels: unknown[]
|
||||
labels: string[]
|
||||
qqLevel: QQLevel
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { encode } from "silk-wasm";
|
||||
import { encode } from 'silk-wasm';
|
||||
|
||||
export interface EncodeArgs {
|
||||
input: ArrayBufferView | ArrayBuffer
|
||||
|
@@ -4,8 +4,8 @@ import path from 'node:path';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { EncodeResult, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
|
||||
import { LogWrapper } from '@/common/log';
|
||||
import { EncodeArgs } from "@/common/audio-worker";
|
||||
import { FFmpegService } from "@/common/ffmpeg";
|
||||
import { EncodeArgs } from '@/common/audio-worker';
|
||||
import { FFmpegService } from '@/common/ffmpeg';
|
||||
|
||||
const ALLOW_SAMPLE_RATE = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
|
||||
|
||||
@@ -27,12 +27,11 @@ async function guessDuration(pttPath: string, logger: LogWrapper) {
|
||||
async function handleWavFile(
|
||||
file: Buffer,
|
||||
filePath: string,
|
||||
pcmPath: string,
|
||||
logger: LogWrapper
|
||||
pcmPath: string
|
||||
): Promise<{ input: Buffer; sampleRate: number }> {
|
||||
const { fmt } = getWavFileInfo(file);
|
||||
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
|
||||
return { input: await FFmpegService.convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
||||
return { input: await FFmpegService.convert(filePath, pcmPath), sampleRate: 24000 };
|
||||
}
|
||||
return { input: file, sampleRate: fmt.sampleRate };
|
||||
}
|
||||
@@ -45,8 +44,8 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
||||
logger.log(`语音文件${filePath}需要转换成silk`);
|
||||
const pcmPath = `${pttPath}.pcm`;
|
||||
const { input, sampleRate } = isWav(file)
|
||||
? (await handleWavFile(file, filePath, pcmPath, logger))
|
||||
: { input: await FFmpegService.convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
||||
? (await handleWavFile(file, filePath, pcmPath))
|
||||
: { input: await FFmpegService.convert(filePath, pcmPath), sampleRate: 24000 };
|
||||
const silk = await piscina.run({ input: input, sampleRate: sampleRate });
|
||||
await fsPromise.writeFile(pttPath, Buffer.from(silk.data));
|
||||
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
||||
@@ -59,8 +58,8 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
||||
let duration = 0;
|
||||
try {
|
||||
duration = getDuration(file) / 1000;
|
||||
} catch (e: any) {
|
||||
logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, e.stack);
|
||||
} catch (e: unknown) {
|
||||
logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, (e as Error).stack);
|
||||
duration = await guessDuration(filePath, logger);
|
||||
}
|
||||
return {
|
||||
@@ -69,8 +68,8 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
||||
duration,
|
||||
};
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.logError('convert silk failed', error.stack);
|
||||
} catch (error: unknown) {
|
||||
logger.logError('convert silk failed', (error as Error).stack);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
export type TaskExecutor<T> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void, onCancel: (callback: () => void) => void) => void | Promise<void>;
|
||||
|
||||
export class CancelableTask<T> {
|
||||
@@ -7,30 +8,34 @@ export class CancelableTask<T> {
|
||||
private cancelListeners: Array<() => void> = [];
|
||||
|
||||
constructor(executor: TaskExecutor<T>) {
|
||||
this.promise = new Promise<T>(async (resolve, reject) => {
|
||||
this.promise = new Promise<T>((resolve, reject) => {
|
||||
const onCancel = (callback: () => void) => {
|
||||
this.cancelCallback = callback;
|
||||
};
|
||||
|
||||
try {
|
||||
await executor(
|
||||
(value) => {
|
||||
if (!this.isCanceled) {
|
||||
resolve(value);
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
if (!this.isCanceled) {
|
||||
reject(reason);
|
||||
}
|
||||
},
|
||||
onCancel
|
||||
);
|
||||
} catch (error) {
|
||||
if (!this.isCanceled) {
|
||||
reject(error);
|
||||
const execute = async () => {
|
||||
try {
|
||||
await executor(
|
||||
(value) => {
|
||||
if (!this.isCanceled) {
|
||||
resolve(value);
|
||||
}
|
||||
},
|
||||
(reason) => {
|
||||
if (!this.isCanceled) {
|
||||
reject(reason);
|
||||
}
|
||||
},
|
||||
onCancel
|
||||
);
|
||||
} catch (error) {
|
||||
if (!this.isCanceled) {
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
execute();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -73,40 +78,3 @@ export class CancelableTask<T> {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function demoAwait() {
|
||||
const executor: TaskExecutor<number> = async (resolve, reject, onCancel) => {
|
||||
let count = 0;
|
||||
const intervalId = setInterval(() => {
|
||||
count++;
|
||||
console.log(`Task is running... Count: ${count}`);
|
||||
if (count === 5) {
|
||||
clearInterval(intervalId);
|
||||
resolve(count);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
onCancel(() => {
|
||||
clearInterval(intervalId);
|
||||
console.log('Task has been canceled.');
|
||||
reject(new Error('Task was canceled'));
|
||||
});
|
||||
};
|
||||
|
||||
const task = new CancelableTask(executor);
|
||||
|
||||
task.onCancel(() => {
|
||||
console.log('Cancel listener triggered.');
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
task.cancel(); // 取消任务
|
||||
}, 6000);
|
||||
|
||||
try {
|
||||
const result = await task;
|
||||
console.log(`Task completed with result: ${result}`);
|
||||
} catch (error) {
|
||||
console.error('Task failed:', error);
|
||||
}
|
||||
}
|
@@ -39,9 +39,9 @@ export abstract class ConfigBase<T> {
|
||||
if (!fs.existsSync(configPath) && copy_default) {
|
||||
try {
|
||||
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
|
||||
this.core.context.logger.log(`[Core] [Config] 配置文件创建成功!\n`);
|
||||
} catch (e: any) {
|
||||
this.core.context.logger.logError(`[Core] [Config] 创建配置文件时发生错误:`, e.message);
|
||||
this.core.context.logger.log('[Core] [Config] 配置文件创建成功!\n');
|
||||
} catch (e: unknown) {
|
||||
this.core.context.logger.logError('[Core] [Config] 创建配置文件时发生错误:', (e as Error).message);
|
||||
}
|
||||
} else if (!fs.existsSync(configPath) && !copy_default) {
|
||||
fs.writeFileSync(configPath, '{}');
|
||||
@@ -50,11 +50,11 @@ export abstract class ConfigBase<T> {
|
||||
this.configData = json5.parse(fs.readFileSync(configPath, 'utf-8'));
|
||||
this.core.context.logger.logDebug(`[Core] [Config] 配置文件${configPath}加载`, this.configData);
|
||||
return this.configData;
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof SyntaxError) {
|
||||
this.core.context.logger.logError(`[Core] [Config] 配置文件格式错误,请检查配置文件:`, e.message);
|
||||
this.core.context.logger.logError('[Core] [Config] 配置文件格式错误,请检查配置文件:', e.message);
|
||||
} else {
|
||||
this.core.context.logger.logError(`[Core] [Config] 读取配置文件时发生错误:`, e.message);
|
||||
this.core.context.logger.logError('[Core] [Config] 读取配置文件时发生错误:', (e as Error).message);
|
||||
}
|
||||
return {} as T;
|
||||
}
|
||||
@@ -67,8 +67,8 @@ export abstract class ConfigBase<T> {
|
||||
const configPath = this.getConfigPath(selfInfo.uin);
|
||||
try {
|
||||
fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2));
|
||||
} catch (e: any) {
|
||||
this.core.context.logger.logError(`保存配置文件 ${configPath} 时发生错误:`, e.message);
|
||||
} catch (e: unknown) {
|
||||
this.core.context.logger.logError(`保存配置文件 ${configPath} 时发生错误:`, (e as Error).message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,22 +0,0 @@
|
||||
// decoratorAsyncMethod(this,function,wrapper)
|
||||
async function decoratorMethod<T, R>(
|
||||
target: T,
|
||||
method: () => Promise<R>,
|
||||
wrapper: (result: R) => Promise<any>,
|
||||
executeImmediately: boolean = true
|
||||
): Promise<any> {
|
||||
const execute = async () => {
|
||||
try {
|
||||
const result = await method.call(target);
|
||||
return wrapper(result);
|
||||
} catch (error) {
|
||||
return Promise.reject(error instanceof Error ? error : new Error(String(error)));
|
||||
}
|
||||
};
|
||||
|
||||
if (executeImmediately) {
|
||||
return execute();
|
||||
} else {
|
||||
return execute;
|
||||
}
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { NodeIQQNTWrapperSession } from '@/core/wrapper';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { ListenerNamingMapping, ServiceNamingMapping } from '@/core';
|
||||
@@ -60,17 +61,22 @@ export class NTEventWrapper {
|
||||
[key: string]: () => { [key: string]: (...params: Parameters<T>) => Promise<ReturnType<T>> };
|
||||
};
|
||||
if (eventNameArr.length > 1) {
|
||||
const serviceName = 'get' + eventNameArr[0].replace('NodeIKernel', '');
|
||||
const serviceName = 'get' + (eventNameArr[0]?.replace('NodeIKernel', '') ?? '');
|
||||
const eventName = eventNameArr[1];
|
||||
const services = (this.WrapperSession as unknown as eventType)[serviceName]();
|
||||
const services = (this.WrapperSession as unknown as eventType)[serviceName]?.();
|
||||
if (!services || !eventName) {
|
||||
return undefined;
|
||||
}
|
||||
let event = services[eventName];
|
||||
|
||||
//重新绑定this
|
||||
event = event.bind(services);
|
||||
event = event?.bind(services);
|
||||
if (event) {
|
||||
return event as T;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
createListenerFunction<T>(listenerMainName: string, uniqueCode: string = ''): T {
|
||||
@@ -126,8 +132,8 @@ export class NTEventWrapper {
|
||||
) {
|
||||
return new Promise<Parameters<ListenerType>>((resolve, reject) => {
|
||||
const ListenerNameList = listenerAndMethod.split('/');
|
||||
const ListenerMainName = ListenerNameList[0];
|
||||
const ListenerSubName = ListenerNameList[1];
|
||||
const ListenerMainName = ListenerNameList[0] ?? '';
|
||||
const ListenerSubName = ListenerNameList[1] ?? '';
|
||||
const id = randomUUID();
|
||||
let complete = 0;
|
||||
let retData: Parameters<ListenerType> | undefined = undefined;
|
||||
@@ -205,8 +211,8 @@ export class NTEventWrapper {
|
||||
}
|
||||
|
||||
const ListenerNameList = listenerAndMethod.split('/');
|
||||
const ListenerMainName = ListenerNameList[0];
|
||||
const ListenerSubName = ListenerNameList[1];
|
||||
const ListenerMainName = ListenerNameList[0]??'';
|
||||
const ListenerSubName = ListenerNameList[1]??'';
|
||||
|
||||
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
|
||||
(resolve, reject) => {
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { FFmpeg } from '@ffmpeg.wasm/main';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { readFileSync, statSync, writeFileSync } from 'fs';
|
||||
import type { LogWrapper } from './log';
|
||||
import type { VideoInfo } from './video';
|
||||
import { fileTypeFromFile } from 'file-type';
|
||||
import imageSize from 'image-size';
|
||||
class FFmpegService {
|
||||
class FFmpegService {
|
||||
public static async extractThumbnail(videoPath: string, thumbnailPath: string): Promise<void> {
|
||||
const ffmpegInstance = await FFmpeg.create({ core: '@ffmpeg.wasm/core-mt' });
|
||||
const videoFileName = `${randomUUID()}.mp4`;
|
||||
const outputFileName = `${randomUUID()}.jpg`;
|
||||
try {
|
||||
ffmpegInstance.fs.writeFile(videoFileName, readFileSync(videoPath));
|
||||
let code = await ffmpegInstance.run('-i', videoFileName, '-ss', '00:00:01.000', '-vframes', '1', outputFileName);
|
||||
const code = await ffmpegInstance.run('-i', videoFileName, '-ss', '00:00:01.000', '-vframes', '1', outputFileName);
|
||||
if (code !== 0) {
|
||||
throw new Error('Error extracting thumbnail: FFmpeg process exited with code ' + code);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ import imageSize from 'image-size';
|
||||
const params = format === 'amr'
|
||||
? ['-f', 's16le', '-ar', '24000', '-ac', '1', '-i', inputFileName, '-ar', '8000', '-b:a', '12.2k', outputFileName]
|
||||
: ['-f', 's16le', '-ar', '24000', '-ac', '1', '-i', inputFileName, outputFileName];
|
||||
let code = await ffmpegInstance.run(...params);
|
||||
const code = await ffmpegInstance.run(...params);
|
||||
if (code !== 0) {
|
||||
throw new Error('Error extracting thumbnail: FFmpeg process exited with code ' + code);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ import imageSize from 'image-size';
|
||||
try {
|
||||
ffmpegInstance.fs.writeFile(inputFileName, readFileSync(filePath));
|
||||
const params = ['-y', '-i', inputFileName, '-ar', '24000', '-ac', '1', '-f', 's16le', outputFileName];
|
||||
let code = await ffmpegInstance.run(...params);
|
||||
const code = await ffmpegInstance.run(...params);
|
||||
if (code !== 0) {
|
||||
throw new Error('FFmpeg process exited with code ' + code);
|
||||
}
|
||||
@@ -99,24 +99,24 @@ import imageSize from 'image-size';
|
||||
|
||||
public static async getVideoInfo(videoPath: string, thumbnailPath: string): Promise<VideoInfo> {
|
||||
await FFmpegService.extractThumbnail(videoPath, thumbnailPath);
|
||||
let fileType = (await fileTypeFromFile(videoPath))?.ext ?? 'mp4';
|
||||
const fileType = (await fileTypeFromFile(videoPath))?.ext ?? 'mp4';
|
||||
const inputFileName = `${randomUUID()}.${fileType}`;
|
||||
const ffmpegInstance = await FFmpeg.create({ core: '@ffmpeg.wasm/core-mt' });
|
||||
ffmpegInstance.fs.writeFile(inputFileName, readFileSync(videoPath));
|
||||
ffmpegInstance.setLogging(true);
|
||||
let duration = 60;
|
||||
ffmpegInstance.setLogger((level, ...msg) => {
|
||||
ffmpegInstance.setLogger((_level, ...msg) => {
|
||||
const message = msg.join(' ');
|
||||
const durationMatch = message.match(/Duration: (\d+):(\d+):(\d+\.\d+)/);
|
||||
if (durationMatch) {
|
||||
const hours = parseInt(durationMatch[1], 10);
|
||||
const minutes = parseInt(durationMatch[2], 10);
|
||||
const seconds = parseFloat(durationMatch[3]);
|
||||
const hours = parseInt(durationMatch[1] ?? '0', 10);
|
||||
const minutes = parseInt(durationMatch[2] ?? '0', 10);
|
||||
const seconds = parseFloat(durationMatch[3] ?? '0');
|
||||
duration = hours * 3600 + minutes * 60 + seconds;
|
||||
}
|
||||
});
|
||||
await ffmpegInstance.run('-i', inputFileName);
|
||||
let image = imageSize(thumbnailPath);
|
||||
const image = imageSize(thumbnailPath);
|
||||
ffmpegInstance.fs.unlink(inputFileName);
|
||||
const fileSize = statSync(videoPath).size;
|
||||
return {
|
||||
@@ -126,7 +126,7 @@ import imageSize from 'image-size';
|
||||
format: fileType,
|
||||
size: fileSize,
|
||||
filePath: videoPath
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
type FFmpegMethod = 'extractThumbnail' | 'convertFile' | 'convert' | 'getVideoInfo';
|
||||
@@ -137,15 +137,15 @@ interface FFmpegTask {
|
||||
}
|
||||
export default async function handleFFmpegTask({ method, args }: FFmpegTask): Promise<any> {
|
||||
switch (method) {
|
||||
case 'extractThumbnail':
|
||||
return await FFmpegService.extractThumbnail(...args as [string, string]);
|
||||
case 'convertFile':
|
||||
return await FFmpegService.convertFile(...args as [string, string, string]);
|
||||
case 'convert':
|
||||
return await FFmpegService.convert(...args as [string, string]);
|
||||
case 'getVideoInfo':
|
||||
return await FFmpegService.getVideoInfo(...args as [string, string]);
|
||||
default:
|
||||
throw new Error(`Unknown method: ${method}`);
|
||||
case 'extractThumbnail':
|
||||
return await FFmpegService.extractThumbnail(...args as [string, string]);
|
||||
case 'convertFile':
|
||||
return await FFmpegService.convertFile(...args as [string, string, string]);
|
||||
case 'convert':
|
||||
return await FFmpegService.convert(...args as [string, string]);
|
||||
case 'getVideoInfo':
|
||||
return await FFmpegService.getVideoInfo(...args as [string, string]);
|
||||
default:
|
||||
throw new Error(`Unknown method: ${method}`);
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
import Piscina from "piscina";
|
||||
import { VideoInfo } from "./video";
|
||||
import type { LogWrapper } from "./log";
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import Piscina from 'piscina';
|
||||
import { VideoInfo } from './video';
|
||||
|
||||
type EncodeArgs = {
|
||||
method: 'extractThumbnail' | 'convertFile' | 'convert' | 'getVideoInfo';
|
||||
|
@@ -83,7 +83,7 @@ class FileUUIDManager {
|
||||
this.cache = new TimeBasedCache<string, FileUUIDData>(5000, ttl);
|
||||
}
|
||||
|
||||
public encode(data: FileUUIDData, endString: string = "", customUUID?: string): string {
|
||||
public encode(data: FileUUIDData, endString: string = '', customUUID?: string): string {
|
||||
const uuid = customUUID ? customUUID : randomUUID().replace(/-/g, '') + endString;
|
||||
this.cache.put(uuid, data);
|
||||
return uuid;
|
||||
@@ -101,7 +101,7 @@ export class FileNapCatOneBotUUIDWrap {
|
||||
this.manager = new FileUUIDManager(ttl);
|
||||
}
|
||||
|
||||
public encodeModelId(peer: Peer, modelId: string, fileId: string, fileUUID: string = "", endString: string = "", customUUID?: string): string {
|
||||
public encodeModelId(peer: Peer, modelId: string, fileId: string, fileUUID: string = '', endString: string = '', customUUID?: string): string {
|
||||
return this.manager.encode({ peer, modelId, fileId, fileUUID }, endString, customUUID);
|
||||
}
|
||||
|
||||
@@ -109,8 +109,8 @@ export class FileNapCatOneBotUUIDWrap {
|
||||
return this.manager.decode(uuid);
|
||||
}
|
||||
|
||||
public encode(peer: Peer, msgId: string, elementId: string, fileUUID: string = "", customUUID?: string): string {
|
||||
return this.manager.encode({ peer, msgId, elementId, fileUUID }, "", customUUID);
|
||||
public encode(peer: Peer, msgId: string, elementId: string, fileUUID: string = '', customUUID?: string): string {
|
||||
return this.manager.encode({ peer, msgId, elementId, fileUUID }, '', customUUID);
|
||||
}
|
||||
|
||||
public decode(uuid: string): FileUUIDData | undefined {
|
||||
|
@@ -58,8 +58,8 @@ function timeoutPromise(timeout: number, errorMsg: string): Promise<void> {
|
||||
async function checkFile(path: string): Promise<void> {
|
||||
try {
|
||||
await stat(path);
|
||||
} catch (error: any) {
|
||||
if (error.code === 'ENOENT') {
|
||||
} catch (error: unknown) {
|
||||
if ((error as Error & { code: string }).code === 'ENOENT') {
|
||||
// 如果文件不存在,则抛出一个错误
|
||||
throw new Error(`文件不存在: ${path}`);
|
||||
} else {
|
||||
@@ -169,6 +169,7 @@ export async function checkUriType(Uri: string) {
|
||||
const data = uri.split(',')[1];
|
||||
if (data) return { Uri: data, Type: FileUriType.Base64 };
|
||||
}
|
||||
return;
|
||||
}, Uri);
|
||||
if (OtherFileRet) return OtherFileRet;
|
||||
|
||||
@@ -190,7 +191,7 @@ export async function uriToLocalFile(dir: string, uri: string, filename: string
|
||||
}
|
||||
|
||||
case FileUriType.Remote: {
|
||||
const buffer = await httpDownload({ url: HandledUri, headers: headers });
|
||||
const buffer = await httpDownload({ url: HandledUri, headers: headers ?? {} });
|
||||
fs.writeFileSync(filePath, buffer);
|
||||
return { success: true, errMsg: '', fileName: filename, path: filePath };
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as crypto from "node:crypto";
|
||||
import { PacketMsg } from "@/core/packet/message/message";
|
||||
import * as crypto from 'node:crypto';
|
||||
import { PacketMsg } from '@/core/packet/message/message';
|
||||
|
||||
interface ForwardMsgJson {
|
||||
app: string
|
||||
@@ -50,15 +50,15 @@ interface ForwardAdaptMsgElement {
|
||||
}
|
||||
|
||||
export class ForwardMsgBuilder {
|
||||
private static build(resId: string, msg: ForwardAdaptMsg[], source?: string, news?: ForwardMsgJsonMetaDetail["news"], summary?: string, prompt?: string): ForwardMsgJson {
|
||||
private static build(resId: string, msg: ForwardAdaptMsg[], source?: string, news?: ForwardMsgJsonMetaDetail['news'], summary?: string, prompt?: string): ForwardMsgJson {
|
||||
const id = crypto.randomUUID();
|
||||
const isGroupMsg = msg.some(m => m.isGroupMsg);
|
||||
if (!source) {
|
||||
source = isGroupMsg ? "群聊的聊天记录" : msg.map(m => m.senderName).filter((v, i, a) => a.indexOf(v) === i).slice(0, 4).join('和') + '的聊天记录';
|
||||
source = isGroupMsg ? '群聊的聊天记录' : msg.map(m => m.senderName).filter((v, i, a) => a.indexOf(v) === i).slice(0, 4).join('和') + '的聊天记录';
|
||||
}
|
||||
if (!news) {
|
||||
news = msg.length === 0 ? [{
|
||||
text: "Nya~ This message is send from NapCat.Packet!",
|
||||
text: 'Nya~ This message is send from NapCat.Packet!',
|
||||
}] : msg.map(m => ({
|
||||
text: `${m.senderName}: ${m.msg?.map(msg => msg.preview).join('')}`,
|
||||
}));
|
||||
@@ -67,15 +67,15 @@ export class ForwardMsgBuilder {
|
||||
summary = `查看${msg.length}条转发消息`;
|
||||
}
|
||||
if (!prompt) {
|
||||
prompt = "[聊天记录]";
|
||||
prompt = '[聊天记录]';
|
||||
}
|
||||
return {
|
||||
app: "com.tencent.multimsg",
|
||||
app: 'com.tencent.multimsg',
|
||||
config: {
|
||||
autosize: 1,
|
||||
forward: 1,
|
||||
round: 1,
|
||||
type: "normal",
|
||||
type: 'normal',
|
||||
width: 300
|
||||
},
|
||||
desc: prompt,
|
||||
@@ -93,8 +93,8 @@ export class ForwardMsgBuilder {
|
||||
}
|
||||
},
|
||||
prompt,
|
||||
ver: "0.0.0.5",
|
||||
view: "contact",
|
||||
ver: '0.0.0.5',
|
||||
view: 'contact',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -102,12 +102,12 @@ export class ForwardMsgBuilder {
|
||||
return this.build(resId, []);
|
||||
}
|
||||
|
||||
static fromPacketMsg(resId: string, packetMsg: PacketMsg[], source?: string, news?: ForwardMsgJsonMetaDetail["news"], summary?: string, prompt?: string): ForwardMsgJson {
|
||||
static fromPacketMsg(resId: string, packetMsg: PacketMsg[], source?: string, news?: ForwardMsgJsonMetaDetail['news'], summary?: string, prompt?: string): ForwardMsgJson {
|
||||
return this.build(resId, packetMsg.map(msg => ({
|
||||
senderName: msg.senderName,
|
||||
isGroupMsg: msg.groupId !== undefined,
|
||||
msg: msg.msg.map(m => ({
|
||||
preview: m.valid ? m.toPreview() : "[该消息类型暂不支持查看]",
|
||||
preview: m.valid ? m.toPreview() : '[该消息类型暂不支持查看]',
|
||||
}))
|
||||
})), source, news, summary, prompt);
|
||||
}
|
||||
|
@@ -1,14 +1,16 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import path from 'node:path';
|
||||
import fs from 'fs';
|
||||
import os from 'node:os';
|
||||
import { QQLevel } from '@/core';
|
||||
import { QQVersionConfigType } from './types';
|
||||
|
||||
export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ...args: Parameters<T>): Promise<ReturnType<T> | undefined> {
|
||||
return new Promise<ReturnType<T> | undefined>((resolve) => {
|
||||
try {
|
||||
const result = func(...args);
|
||||
resolve(result);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
@@ -166,14 +168,14 @@ export function calcQQLevel(level?: QQLevel) {
|
||||
}
|
||||
|
||||
export function stringifyWithBigInt(obj: any) {
|
||||
return JSON.stringify(obj, (key, value) =>
|
||||
return JSON.stringify(obj, (_key, value) =>
|
||||
typeof value === 'bigint' ? value.toString() : value
|
||||
);
|
||||
}
|
||||
|
||||
export function parseAppidFromMajor(nodeMajor: string): string | undefined {
|
||||
const hexSequence = "A4 09 00 00 00 35";
|
||||
const sequenceBytes = Buffer.from(hexSequence.replace(/ /g, ""), "hex");
|
||||
const hexSequence = 'A4 09 00 00 00 35';
|
||||
const sequenceBytes = Buffer.from(hexSequence.replace(/ /g, ''), 'hex');
|
||||
const filePath = path.resolve(nodeMajor);
|
||||
const fileContent = fs.readFileSync(filePath);
|
||||
|
||||
@@ -192,8 +194,8 @@ export function parseAppidFromMajor(nodeMajor: string): string | undefined {
|
||||
const content = fileContent.subarray(start, end);
|
||||
if (!content.every(byte => byte === 0x00)) {
|
||||
try {
|
||||
return content.toString("utf-8");
|
||||
} catch (error) {
|
||||
return content.toString('utf-8');
|
||||
} catch {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import winston, { format, transports } from 'winston';
|
||||
import { truncateString } from '@/common/helper';
|
||||
import path from 'node:path';
|
||||
@@ -34,7 +35,7 @@ class Subscription {
|
||||
for (const history of Subscription.history) {
|
||||
try {
|
||||
listener(history);
|
||||
} catch (_) {
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -68,7 +69,7 @@ export class LogWrapper {
|
||||
format: format.combine(
|
||||
format.timestamp({ format: 'MM-DD HH:mm:ss' }),
|
||||
format.printf(({ timestamp, level, message, ...meta }) => {
|
||||
const userInfo = meta.userInfo ? `${meta.userInfo} | ` : '';
|
||||
const userInfo = meta['userInfo'] ? `${meta['userInfo']} | ` : '';
|
||||
return `${timestamp} [${level}] ${userInfo}${message}`;
|
||||
})
|
||||
),
|
||||
@@ -83,7 +84,7 @@ export class LogWrapper {
|
||||
format: format.combine(
|
||||
format.colorize(),
|
||||
format.printf(({ timestamp, level, message, ...meta }) => {
|
||||
const userInfo = meta.userInfo ? `${meta.userInfo} | ` : '';
|
||||
const userInfo = meta['userInfo'] ? `${meta['userInfo']} | ` : '';
|
||||
return `${timestamp} [${level}] ${userInfo}${message}`;
|
||||
})
|
||||
),
|
||||
@@ -303,7 +304,7 @@ function textElementToText(textElement: any): string {
|
||||
const originalContentLines = textElement.content.split('\n');
|
||||
return `${originalContentLines[0]}${originalContentLines.length > 1 ? ' ...' : ''}`;
|
||||
} else if (textElement.atType === NTMsgAtType.ATTYPEALL) {
|
||||
return `@全体成员`;
|
||||
return '@全体成员';
|
||||
} else if (textElement.atType === NTMsgAtType.ATTYPEONE) {
|
||||
return `${textElement.content} (${textElement.atUid})`;
|
||||
}
|
||||
|
@@ -68,7 +68,10 @@ export class LimitedHashTable<K, V> {
|
||||
const listSize = Math.min(size, keyList.length);
|
||||
for (let i = 0; i < listSize; i++) {
|
||||
const key = keyList[listSize - i];
|
||||
result.push({ key, value: this.keyToValue.get(key)! });
|
||||
if (key !== undefined) {
|
||||
result.push({ key, value: this.keyToValue.get(key)! });
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -96,8 +99,10 @@ class MessageUniqueWrapper {
|
||||
createUniqueMsgId(peer: Peer, msgId: string) {
|
||||
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
||||
const hash = crypto.createHash('md5').update(key).digest();
|
||||
//设置第一个bit为0 保证shortId为正数
|
||||
hash[0] &= 0x7f;
|
||||
if (hash[0]) {
|
||||
//设置第一个bit为0 保证shortId为正数
|
||||
hash[0] &= 0x7f;
|
||||
}
|
||||
const shortId = hash.readInt32BE(0);
|
||||
//减少性能损耗
|
||||
this.msgIdMap.set(msgId, shortId);
|
||||
@@ -110,11 +115,11 @@ class MessageUniqueWrapper {
|
||||
if (data) {
|
||||
const [msgId, chatTypeStr, peerUid] = data.split('|');
|
||||
const peer: Peer = {
|
||||
chatType: parseInt(chatTypeStr),
|
||||
peerUid,
|
||||
chatType: parseInt(chatTypeStr ?? '0'),
|
||||
peerUid: peerUid ?? '',
|
||||
guildId: '',
|
||||
};
|
||||
return { MsgId: msgId, Peer: peer };
|
||||
return { MsgId: msgId ?? '0', Peer: peer };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { LogWrapper } from '@/common/log';
|
||||
|
||||
export function proxyHandlerOf(logger: LogWrapper) {
|
||||
@@ -5,6 +6,7 @@ export function proxyHandlerOf(logger: LogWrapper) {
|
||||
get(target: any, prop: any, receiver: any) {
|
||||
if (typeof target[prop] === 'undefined') {
|
||||
// 如果方法不存在,返回一个函数,这个函数调用existentMethod
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
return (..._args: unknown[]) => {
|
||||
logger.logDebug(`${target.constructor.name} has no method ${prop}`);
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@ import { getDefaultQQVersionConfigInfo, getQQPackageInfoPath, getQQVersionConfig
|
||||
import AppidTable from '@/core/external/appid.json';
|
||||
import { LogWrapper } from '@/common/log';
|
||||
import { getMajorPath } from '@/core';
|
||||
import { QQAppidTableType, QQPackageInfoType, QQVersionConfigType } from './types';
|
||||
|
||||
export class QQBasicInfoWrapper {
|
||||
QQMainPath: string | undefined;
|
||||
@@ -86,14 +87,14 @@ export class QQBasicInfoWrapper {
|
||||
try {
|
||||
const majorAppid = this.getAppidV2ByMajor(fullVersion);
|
||||
if (majorAppid) {
|
||||
this.context.logger.log(`[QQ版本兼容性检测] 当前版本Appid未内置 通过Major获取 为了更好的性能请尝试更新NapCat`);
|
||||
this.context.logger.log('[QQ版本兼容性检测] 当前版本Appid未内置 通过Major获取 为了更好的性能请尝试更新NapCat');
|
||||
return { appid: majorAppid, qua: this.getQUAFallback() };
|
||||
}
|
||||
} catch (error) {
|
||||
this.context.logger.log(`[QQ版本兼容性检测] 通过Major 获取Appid异常 请检测NapCat/QQNT是否正常`);
|
||||
} catch {
|
||||
this.context.logger.log('[QQ版本兼容性检测] 通过Major 获取Appid异常 请检测NapCat/QQNT是否正常');
|
||||
}
|
||||
// 最终兜底为老版本
|
||||
this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`);
|
||||
this.context.logger.log('[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常');
|
||||
this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,);
|
||||
return { appid: this.getAppIdFallback(), qua: this.getQUAFallback() };
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import https from 'node:https';
|
||||
import http from 'node:http';
|
||||
|
||||
@@ -41,11 +42,13 @@ export class RequestUtil {
|
||||
|
||||
private static extractCookies(setCookieHeaders: string[], cookies: { [key: string]: string }) {
|
||||
setCookieHeaders.forEach((cookie) => {
|
||||
const parts = cookie.split(';')[0].split('=');
|
||||
const key = parts[0];
|
||||
const value = parts[1];
|
||||
if (key && value && key.length > 0 && value.length > 0) {
|
||||
cookies[key] = value;
|
||||
const parts = cookie.split(';')[0]?.split('=');
|
||||
if (parts) {
|
||||
const key = parts[0];
|
||||
const value = parts[1];
|
||||
if (key && value && key.length > 0 && value.length > 0) {
|
||||
cookies[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -54,10 +54,10 @@ class Store {
|
||||
// 分批次扫描
|
||||
while (scanned < this.scanLimit && this.scanCursor < keys.length) {
|
||||
const key = keys[this.scanCursor++];
|
||||
const entry = this.store.get(key)!;
|
||||
const entry = this.store.get(key!)!;
|
||||
|
||||
if (entry.expiresAt && entry.expiresAt < now) {
|
||||
this.store.delete(key);
|
||||
this.store.delete(key!);
|
||||
}
|
||||
|
||||
scanned++;
|
||||
|
@@ -6,7 +6,7 @@ let osName: string;
|
||||
|
||||
try {
|
||||
osName = os.hostname();
|
||||
} catch (e) {
|
||||
} catch {
|
||||
osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4);
|
||||
}
|
||||
|
||||
|
@@ -1,17 +1,17 @@
|
||||
//QQVersionType
|
||||
type QQPackageInfoType = {
|
||||
export type QQPackageInfoType = {
|
||||
version: string;
|
||||
buildVersion: string;
|
||||
platform: string;
|
||||
eleArch: string;
|
||||
}
|
||||
type QQVersionConfigType = {
|
||||
export type QQVersionConfigType = {
|
||||
baseVersion: string;
|
||||
curVersion: string;
|
||||
prevVersion: string;
|
||||
onErrorVersions: Array<any>;
|
||||
onErrorVersions: Array<unknown>;
|
||||
buildId: string;
|
||||
}
|
||||
type QQAppidTableType = {
|
||||
export type QQAppidTableType = {
|
||||
[key: string]: { appid: string, qua: string };
|
||||
}
|
||||
|
@@ -1,15 +1,16 @@
|
||||
import { MsfChangeReasonType, MsfStatusType } from "@/core/types/adapter";
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { MsfChangeReasonType, MsfStatusType } from '@/core/types/adapter';
|
||||
|
||||
export class NodeIDependsAdapter {
|
||||
onMSFStatusChange(statusType: MsfStatusType, changeReasonType: MsfChangeReasonType) {
|
||||
onMSFStatusChange(_statusType: MsfStatusType, _changeReasonType: MsfChangeReasonType) {
|
||||
|
||||
}
|
||||
|
||||
onMSFSsoError(args: unknown) {
|
||||
onMSFSsoError(_args: unknown) {
|
||||
|
||||
}
|
||||
|
||||
getGroupCode(args: unknown) {
|
||||
getGroupCode(_args: unknown) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
export class NodeIDispatcherAdapter {
|
||||
dispatchRequest(arg: unknown) {
|
||||
dispatchRequest(_arg: unknown) {
|
||||
}
|
||||
|
||||
dispatchCall(arg: unknown) {
|
||||
dispatchCall(_arg: unknown) {
|
||||
}
|
||||
|
||||
dispatchCallWithJson(arg: unknown) {
|
||||
dispatchCallWithJson(_arg: unknown) {
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +1,26 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
export class NodeIGlobalAdapter {
|
||||
onLog(...args: unknown[]) {
|
||||
onLog(..._args: unknown[]) {
|
||||
}
|
||||
|
||||
onGetSrvCalTime(...args: unknown[]) {
|
||||
onGetSrvCalTime(..._args: unknown[]) {
|
||||
}
|
||||
|
||||
onShowErrUITips(...args: unknown[]) {
|
||||
onShowErrUITips(..._args: unknown[]) {
|
||||
}
|
||||
|
||||
fixPicImgType(...args: unknown[]) {
|
||||
fixPicImgType(..._args: unknown[]) {
|
||||
}
|
||||
|
||||
getAppSetting(...args: unknown[]) {
|
||||
getAppSetting(..._args: unknown[]) {
|
||||
}
|
||||
|
||||
onInstallFinished(...args: unknown[]) {
|
||||
onInstallFinished(..._args: unknown[]) {
|
||||
}
|
||||
|
||||
onUpdateGeneralFlag(...args: unknown[]) {
|
||||
onUpdateGeneralFlag(..._args: unknown[]) {
|
||||
}
|
||||
|
||||
onGetOfflineMsg(...args: unknown[]) {
|
||||
onGetOfflineMsg(..._args: unknown[]) {
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ import { encodeSilk } from '@/common/audio';
|
||||
import { SendMessageContext } from '@/onebot/api';
|
||||
import { getFileTypeForSendType } from '../helper/msg';
|
||||
import { FFmpegService } from '@/common/ffmpeg';
|
||||
import { rkeyDataType } from '../types/file';
|
||||
|
||||
export class NTQQFileApi {
|
||||
context: InstanceContext;
|
||||
@@ -40,7 +41,7 @@ export class NTQQFileApi {
|
||||
this.rkeyManager = new RkeyManager([
|
||||
'https://rkey.napneko.icu/rkeys'
|
||||
],
|
||||
this.context.logger
|
||||
this.context.logger
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,7 +62,7 @@ export class NTQQFileApi {
|
||||
|
||||
async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) {
|
||||
const fileMd5 = await calculateFileMD5(filePath);
|
||||
const extOrEmpty = await fileTypeFromFile(filePath).then(e => e?.ext ?? '').catch(e => '');
|
||||
const extOrEmpty = await fileTypeFromFile(filePath).then(e => e?.ext ?? '').catch(() => '');
|
||||
const ext = extOrEmpty ? `.${extOrEmpty}` : '';
|
||||
let fileName = `${path.basename(filePath)}`;
|
||||
if (fileName.indexOf('.') === -1) {
|
||||
@@ -140,7 +141,7 @@ export class NTQQFileApi {
|
||||
};
|
||||
}
|
||||
|
||||
async createValidSendVideoElement(context: SendMessageContext, filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
|
||||
async createValidSendVideoElement(context: SendMessageContext, filePath: string, fileName: string = '', _diyThumbPath: string = ''): Promise<SendVideoElement> {
|
||||
let videoInfo = {
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
@@ -170,10 +171,16 @@ export class NTQQFileApi {
|
||||
const thumbPath = pathLib.join(pathLib.dirname(thumbDir), `${md5}_0.png`);
|
||||
try {
|
||||
videoInfo = await FFmpegService.getVideoInfo(filePath, thumbPath);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
fs.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64'));
|
||||
}
|
||||
|
||||
if (_diyThumbPath) {
|
||||
try {
|
||||
await this.copyFile(_diyThumbPath, thumbPath);
|
||||
} catch (e) {
|
||||
this.context.logger.logError('复制自定义缩略图失败', e);
|
||||
}
|
||||
}
|
||||
const thumbSize = (await fsPromises.stat(thumbPath)).size;
|
||||
const thumbMd5 = await calculateFileMD5(thumbPath);
|
||||
context.deleteAfterSentFiles.push(path);
|
||||
@@ -274,18 +281,18 @@ export class NTQQFileApi {
|
||||
element.elementType === ElementType.FILE
|
||||
) {
|
||||
switch (element.elementType) {
|
||||
case ElementType.PIC:
|
||||
element.picElement!.sourcePath = elementResults[elementIndex];
|
||||
break;
|
||||
case ElementType.VIDEO:
|
||||
element.videoElement!.filePath = elementResults[elementIndex];
|
||||
break;
|
||||
case ElementType.PTT:
|
||||
element.pttElement!.filePath = elementResults[elementIndex];
|
||||
break;
|
||||
case ElementType.FILE:
|
||||
element.fileElement!.filePath = elementResults[elementIndex];
|
||||
break;
|
||||
case ElementType.PIC:
|
||||
element.picElement!.sourcePath = elementResults?.[elementIndex] ?? '';
|
||||
break;
|
||||
case ElementType.VIDEO:
|
||||
element.videoElement!.filePath = elementResults?.[elementIndex] ?? '';
|
||||
break;
|
||||
case ElementType.PTT:
|
||||
element.pttElement!.filePath = elementResults?.[elementIndex] ?? '';
|
||||
break;
|
||||
case ElementType.FILE:
|
||||
element.fileElement!.filePath = elementResults?.[elementIndex] ?? '';
|
||||
break;
|
||||
}
|
||||
elementIndex++;
|
||||
}
|
||||
@@ -299,7 +306,7 @@ export class NTQQFileApi {
|
||||
if (force) {
|
||||
try {
|
||||
await fsPromises.unlink(sourcePath);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
} else {
|
||||
@@ -401,27 +408,27 @@ export class NTQQFileApi {
|
||||
}
|
||||
|
||||
private async getRkeyData() {
|
||||
const rkeyData = {
|
||||
const rkeyData: rkeyDataType = {
|
||||
private_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qEc3Rbib9LP4',
|
||||
group_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qffcqm614gds',
|
||||
online_rkey: false
|
||||
};
|
||||
|
||||
try {
|
||||
if (this.core.apis.PacketApi.available) {
|
||||
if (this.core.apis.PacketApi.available && this.packetRkey?.[0] && this.packetRkey?.[1]) {
|
||||
const rkey_expired_private = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000;
|
||||
const rkey_expired_group = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000;
|
||||
if (rkey_expired_private || rkey_expired_group) {
|
||||
this.packetRkey = await this.core.apis.PacketApi.pkt.operation.FetchRkey();
|
||||
}
|
||||
if (this.packetRkey && this.packetRkey.length > 0) {
|
||||
rkeyData.group_rkey = this.packetRkey[1].rkey.slice(6);
|
||||
rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6);
|
||||
rkeyData.group_rkey = this.packetRkey[1]?.rkey.slice(6) ?? '';
|
||||
rkeyData.private_rkey = this.packetRkey[0]?.rkey.slice(6) ?? '';
|
||||
rkeyData.online_rkey = true;
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.context.logger.logError('获取rkey失败', error.message);
|
||||
} catch (error: unknown) {
|
||||
this.context.logger.logError('获取rkey失败', (error as Error).message);
|
||||
}
|
||||
|
||||
if (!rkeyData.online_rkey) {
|
||||
@@ -438,7 +445,7 @@ export class NTQQFileApi {
|
||||
return rkeyData;
|
||||
}
|
||||
|
||||
private getImageUrlFromParsedUrl(imageFileId: string, appid: string, rkeyData: any): string {
|
||||
private getImageUrlFromParsedUrl(imageFileId: string, appid: string, rkeyData: rkeyDataType): string {
|
||||
const rkey = appid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
|
||||
if (rkeyData.online_rkey) {
|
||||
return IMAGE_HTTP_HOST_NT + `/download?appid=${appid}&fileid=${imageFileId}&rkey=${rkey}`;
|
||||
|
@@ -13,7 +13,7 @@ export class NTQQFriendApi {
|
||||
async setBuddyRemark(uid: string, remark: string) {
|
||||
return this.context.session.getBuddyService().setBuddyRemark({ uid, remark });
|
||||
}
|
||||
async getBuddyV2SimpleInfoMap(refresh = false) {
|
||||
async getBuddyV2SimpleInfoMap() {
|
||||
const buddyService = this.context.session.getBuddyService();
|
||||
const buddyListV2 = await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
|
||||
const uids = buddyListV2.data.flatMap(item => item.buddyUids);
|
||||
@@ -24,13 +24,13 @@ export class NTQQFriendApi {
|
||||
);
|
||||
}
|
||||
|
||||
async getBuddy(refresh = false): Promise<FriendV2[]> {
|
||||
return Array.from((await this.getBuddyV2SimpleInfoMap(refresh)).values());
|
||||
async getBuddy(): Promise<FriendV2[]> {
|
||||
return Array.from((await this.getBuddyV2SimpleInfoMap()).values());
|
||||
}
|
||||
|
||||
async getBuddyIdMap(refresh = false): Promise<LimitedHashTable<string, string>> {
|
||||
async getBuddyIdMap(): Promise<LimitedHashTable<string, string>> {
|
||||
const retMap: LimitedHashTable<string, string> = new LimitedHashTable<string, string>(5000);
|
||||
const data = await this.getBuddyV2SimpleInfoMap(refresh);
|
||||
const data = await this.getBuddyV2SimpleInfoMap();
|
||||
data.forEach((value) => retMap.set(value.uin!, value.uid!));
|
||||
return retMap;
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ export class NTQQGroupApi {
|
||||
}, pskey);
|
||||
}
|
||||
|
||||
async getGroupShutUpMemberList(groupCode: string) {
|
||||
async getGroupShutUpMemberList(groupCode: string): Promise<ShutUpGroupMember[]> {
|
||||
const executor: TaskExecutor<ShutUpGroupMember[]> = async (resolve, reject, onCancel) => {
|
||||
this.core.eventWrapper.registerListen(
|
||||
'NodeIKernelGroupListener/onShutUpMemberListChanged',
|
||||
@@ -215,6 +215,9 @@ export class NTQQGroupApi {
|
||||
guildId: '',
|
||||
peerUid: groupCode,
|
||||
}, msgId, 1, false);
|
||||
if (!MsgData.msgList[0]) {
|
||||
throw new Error('消息不存在');
|
||||
}
|
||||
const param = {
|
||||
groupCode: groupCode,
|
||||
msgRandom: parseInt(MsgData.msgList[0].msgRandom),
|
||||
@@ -255,6 +258,9 @@ export class NTQQGroupApi {
|
||||
guildId: '',
|
||||
peerUid: groupCode,
|
||||
}, msgId, 1, false);
|
||||
if (!MsgData.msgList[0]) {
|
||||
throw new Error('消息不存在');
|
||||
}
|
||||
const param = {
|
||||
groupCode: groupCode,
|
||||
msgRandom: parseInt(MsgData.msgList[0].msgRandom),
|
||||
|
@@ -5,3 +5,5 @@ export * from './msg';
|
||||
export * from './user';
|
||||
export * from './webapi';
|
||||
export * from './system';
|
||||
export * from './packet';
|
||||
export * from './file';
|
@@ -201,7 +201,7 @@ export class NTQQMsgApi {
|
||||
return this.context.session.getMsgService().getTempChatInfo(chatType, peerUid);
|
||||
}
|
||||
|
||||
async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
||||
async sendMsg(peer: Peer, msgElements: SendMessageElement[], timeout = 10000) {
|
||||
//唉?!我有个想法
|
||||
if (peer.chatType === ChatType.KCHATTYPETEMPC2CFROMGROUP && peer.guildId && peer.guildId !== '') {
|
||||
const member = await this.core.apis.GroupApi.getGroupMember(peer.guildId, peer.peerUid);
|
||||
@@ -268,7 +268,7 @@ export class NTQQMsgApi {
|
||||
if (!arkElement) {
|
||||
continue;
|
||||
}
|
||||
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData ?? '');
|
||||
const forwardData: { app: string } = JSON.parse(arkElement.arkElement?.bytesData ?? '');
|
||||
if (forwardData.app != 'com.tencent.multimsg') {
|
||||
continue;
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as os from 'os';
|
||||
import offset from '@/core/external/offset.json';
|
||||
import { InstanceContext, NapCatCore } from "@/core";
|
||||
import { LogWrapper } from "@/common/log";
|
||||
import { PacketClientSession } from "@/core/packet/clientSession";
|
||||
import { napCatVersion } from "@/common/version";
|
||||
import { InstanceContext, NapCatCore } from '@/core';
|
||||
import { LogWrapper } from '@/common/log';
|
||||
import { PacketClientSession } from '@/core/packet/clientSession';
|
||||
import { napCatVersion } from '@/common/version';
|
||||
|
||||
interface OffsetType {
|
||||
[key: string]: {
|
||||
|
@@ -25,7 +25,7 @@ export class NTQQSystemApi {
|
||||
this.context.session.getMsgService().getOnLineDev();
|
||||
}
|
||||
|
||||
async getArkJsonCollection(cid: string) {
|
||||
async getArkJsonCollection() {
|
||||
return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelCollectionService/collectionArkShare', '1717662698058');
|
||||
}
|
||||
|
||||
|
@@ -69,7 +69,7 @@ export class NTQQUserApi {
|
||||
}
|
||||
|
||||
async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) {
|
||||
const [_retData, profile] = await this.core.eventWrapper.callNormalEventV2(
|
||||
const [, profile] = await this.core.eventWrapper.callNormalEventV2(
|
||||
'NodeIKernelProfileService/fetchUserDetailInfo',
|
||||
'NodeIKernelProfileListener/onUserDetailInfoChanged',
|
||||
[
|
||||
@@ -130,10 +130,10 @@ export class NTQQUserApi {
|
||||
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin +
|
||||
'&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
|
||||
const data = await RequestUtil.HttpsGetCookies(requestUrl);
|
||||
if (!data.p_skey || data.p_skey.length == 0) {
|
||||
if (!data['p_skey'] || data['p_skey'].length == 0) {
|
||||
try {
|
||||
const pskey = (await this.getPSkey([domain])).domainPskeyMap.get(domain);
|
||||
if (pskey) data.p_skey = pskey;
|
||||
if (pskey) data['p_skey'] = pskey;
|
||||
} catch {
|
||||
return data;
|
||||
}
|
||||
@@ -145,7 +145,7 @@ export class NTQQUserApi {
|
||||
return await this.context.session.getTipOffService().getPskey(domainList, true);
|
||||
}
|
||||
|
||||
async getRobotUinRange(): Promise<Array<any>> {
|
||||
async getRobotUinRange(): Promise<Array<unknown>> {
|
||||
const robotUinRanges = await this.context.session.getRobotService().getRobotUinRange({
|
||||
justFetchMsgConfig: '1',
|
||||
type: 1,
|
||||
|
@@ -32,7 +32,7 @@ export class NTQQWebApi {
|
||||
}).toString()}`;
|
||||
try {
|
||||
return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ export class NTQQWebApi {
|
||||
}
|
||||
}
|
||||
|
||||
async getGroupMembers(GroupCode: string, cached: boolean = true): Promise<WebApiGroupMember[]> {
|
||||
async getGroupMembers(GroupCode: string): Promise<WebApiGroupMember[]> {
|
||||
//logDebug('webapi 获取群成员', GroupCode);
|
||||
const memberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>();
|
||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||
@@ -88,7 +88,9 @@ export class NTQQWebApi {
|
||||
return [];
|
||||
} else {
|
||||
for (const key in fastRet.mems) {
|
||||
memberData.push(fastRet.mems[key]);
|
||||
if (fastRet.mems[key]) {
|
||||
memberData.push(fastRet.mems[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
//初始化获取PageNum
|
||||
@@ -116,7 +118,9 @@ export class NTQQWebApi {
|
||||
continue;
|
||||
}
|
||||
for (const key in ret.mems) {
|
||||
memberData.push(ret.mems[key]);
|
||||
if (ret.mems[key]) {
|
||||
memberData.push(ret.mems[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return memberData;
|
||||
@@ -185,7 +189,7 @@ export class NTQQWebApi {
|
||||
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||
);
|
||||
return ret;
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -210,12 +214,12 @@ export class NTQQWebApi {
|
||||
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||
);
|
||||
return ret?.ec === 0 ? ret : undefined;
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private async getDataInternal(cookieObject: any, groupCode: string, type: number) {
|
||||
private async getDataInternal(cookieObject: { [key: string]: string }, groupCode: string, type: number) {
|
||||
let resJson;
|
||||
try {
|
||||
const res = await RequestUtil.HttpGetText(
|
||||
@@ -228,7 +232,7 @@ export class NTQQWebApi {
|
||||
{ 'Cookie': this.cookieToString(cookieObject) }
|
||||
);
|
||||
const match = /window\.__INITIAL_STATE__=(.*?);/.exec(res);
|
||||
if (match) {
|
||||
if (match?.[1]) {
|
||||
resJson = JSON.parse(match[1].trim());
|
||||
}
|
||||
return type === 1 ? resJson?.talkativeList : resJson?.actorList;
|
||||
@@ -238,13 +242,18 @@ export class NTQQWebApi {
|
||||
}
|
||||
}
|
||||
|
||||
private async getHonorList(cookieObject: any, groupCode: string, type: number) {
|
||||
private async getHonorList(cookieObject: { [key: string]: string }, groupCode: string, type: number) {
|
||||
const data = await this.getDataInternal(cookieObject, groupCode, type);
|
||||
if (!data) {
|
||||
this.context.logger.logError(`获取类型 ${type} 的荣誉信息失败`);
|
||||
return [];
|
||||
}
|
||||
return data.map((item: any) => ({
|
||||
return data.map((item: {
|
||||
uin: string,
|
||||
name: string,
|
||||
avatar: string,
|
||||
desc: string,
|
||||
}) => ({
|
||||
user_id: item?.uin,
|
||||
nickname: item?.name,
|
||||
avatar: item?.avatar,
|
||||
@@ -254,7 +263,15 @@ export class NTQQWebApi {
|
||||
|
||||
async getGroupHonorInfo(groupCode: string, getType: WebHonorType) {
|
||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||
const HonorInfo: any = { group_id: groupCode };
|
||||
let HonorInfo = {
|
||||
group_id: groupCode,
|
||||
current_talkative: {},
|
||||
talkative_list: [],
|
||||
performer_list: [],
|
||||
legend_list: [],
|
||||
emotion_list: [],
|
||||
strong_newbie_list: [],
|
||||
};
|
||||
|
||||
if (getType === WebHonorType.TALKATIVE || getType === WebHonorType.ALL) {
|
||||
const talkativeList = await this.getHonorList(cookieObject, groupCode, 1);
|
||||
@@ -284,12 +301,12 @@ export class NTQQWebApi {
|
||||
return HonorInfo;
|
||||
}
|
||||
|
||||
private cookieToString(cookieObject: any) {
|
||||
private cookieToString(cookieObject: { [key: string]: string }) {
|
||||
return Object.entries(cookieObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||
}
|
||||
|
||||
public getBknFromCookie(cookieObject: any) {
|
||||
const sKey = cookieObject.skey as string;
|
||||
public getBknFromCookie(cookieObject: { [key: string]: string }) {
|
||||
const sKey = cookieObject['skey'] as string;
|
||||
|
||||
let hash = 5381;
|
||||
for (let i = 0; i < sKey.length; i++) {
|
||||
@@ -322,18 +339,18 @@ export class NTQQWebApi {
|
||||
data: pskey,
|
||||
appid: 5
|
||||
},
|
||||
appid: "qun",
|
||||
appid: 'qun',
|
||||
checksum: img_md5,
|
||||
check_type: 0,
|
||||
file_len: img_size,
|
||||
env: {
|
||||
refer: "qzone",
|
||||
deviceInfo: "h5"
|
||||
refer: 'qzone',
|
||||
deviceInfo: 'h5'
|
||||
},
|
||||
model: 0,
|
||||
biz_req: {
|
||||
sPicTitle: img_name,
|
||||
sPicDesc: "",
|
||||
sPicDesc: '',
|
||||
sAlbumName: sAlbumName,
|
||||
sAlbumID: sAlbumID,
|
||||
iAlbumTypeID: 0,
|
||||
@@ -341,7 +358,7 @@ export class NTQQWebApi {
|
||||
iUploadType: 0,
|
||||
iUpPicType: 0,
|
||||
iBatchID: time,
|
||||
sPicPath: "",
|
||||
sPicPath: '',
|
||||
iPicWidth: 0,
|
||||
iPicHight: 0,
|
||||
iWaterType: 0,
|
||||
@@ -349,19 +366,19 @@ export class NTQQWebApi {
|
||||
iNeedFeeds: 1,
|
||||
iUploadTime: time,
|
||||
mapExt: {
|
||||
appid: "qun",
|
||||
appid: 'qun',
|
||||
userid: gc
|
||||
}
|
||||
},
|
||||
session: "",
|
||||
session: '',
|
||||
asy_upload: 0,
|
||||
cmd: "FileUpload"
|
||||
cmd: 'FileUpload'
|
||||
}]
|
||||
};
|
||||
const api = `https://h5.qzone.qq.com/webapp/json/sliceUpload/FileBatchControl/${img_md5}?g_tk=${GTK}`;
|
||||
const post = await RequestUtil.HttpGetJson(api, 'POST', body, {
|
||||
"Cookie": cookie,
|
||||
"Content-Type": "application/json"
|
||||
'Cookie': cookie,
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
return post;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// TODO: further refactor in NapCat.Packet v2
|
||||
import { NapProtoMsg, ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { NapProtoMsg, ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
const LikeDetail = {
|
||||
txt: ProtoField(1, ScalarType.STRING),
|
||||
|
@@ -32,7 +32,7 @@ export class RkeyManager {
|
||||
}
|
||||
|
||||
if (this.failureCount >= this.FAILURE_LIMIT) {
|
||||
this.logger.logError(`[Rkey] 服务存在异常, 图片使用FallBack机制`);
|
||||
this.logger.logError('[Rkey] 服务存在异常, 图片使用FallBack机制');
|
||||
throw new Error('获取rkey失败次数过多,请稍后再试');
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ export class RkeyManager {
|
||||
return now > this.rkeyData.expired_time;
|
||||
}
|
||||
|
||||
async refreshRkey(): Promise<any> {
|
||||
async refreshRkey() {
|
||||
//刷新rkey
|
||||
for (const url of this.serverUrl) {
|
||||
try {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import os from "node:os";
|
||||
import EventEmitter from "node:events";
|
||||
import os from 'node:os';
|
||||
import EventEmitter from 'node:events';
|
||||
|
||||
export interface SystemStatus {
|
||||
cpu: {
|
||||
@@ -35,9 +35,9 @@ export class StatusHelper {
|
||||
const { total, active } = currentTimes.map((times, index) => {
|
||||
const prevTimes = this.cpuTimes[index];
|
||||
const totalCurrent = times.user + times.nice + times.sys + times.idle + times.irq;
|
||||
const totalPrev = prevTimes.user + prevTimes.nice + prevTimes.sys + prevTimes.idle + prevTimes.irq;
|
||||
const totalPrev = (prevTimes?.user ?? 0) + (prevTimes?.nice ?? 0) + (prevTimes?.sys ?? 0) + (prevTimes?.idle ?? 0) + (prevTimes?.irq ?? 0);
|
||||
const activeCurrent = totalCurrent - times.idle;
|
||||
const activePrev = totalPrev - prevTimes.idle;
|
||||
const activePrev = totalPrev - (prevTimes?.idle ?? 0);
|
||||
return {
|
||||
total: totalCurrent - totalPrev,
|
||||
active: activeCurrent - activePrev
|
||||
@@ -49,8 +49,8 @@ export class StatusHelper {
|
||||
this.cpuTimes = currentTimes;
|
||||
return {
|
||||
usage: this.replaceNaN(((active / total) * 100)).toFixed(2),
|
||||
model: os.cpus()[0].model,
|
||||
speed: os.cpus()[0].speed,
|
||||
model: os.cpus()[0]?.model ?? 'none',
|
||||
speed: os.cpus()[0]?.speed ?? 0,
|
||||
core: os.cpus().length
|
||||
};
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import { hostname, systemName, systemVersion } from '@/common/system';
|
||||
import { NTEventWrapper } from '@/common/event';
|
||||
import { GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/types';
|
||||
import { KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/types';
|
||||
import { NapCatConfigLoader } from '@/core/helper/config';
|
||||
import os from 'node:os';
|
||||
import { NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners';
|
||||
@@ -52,13 +52,13 @@ export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
|
||||
}
|
||||
let wrapperNodePath = path.resolve(appPath, 'wrapper.node');
|
||||
if (!fs.existsSync(wrapperNodePath)) {
|
||||
wrapperNodePath = path.join(appPath, `./resources/app/wrapper.node`);
|
||||
wrapperNodePath = path.join(appPath, './resources/app/wrapper.node');
|
||||
}
|
||||
//老版本兼容 未来去掉
|
||||
if (!fs.existsSync(wrapperNodePath)) {
|
||||
wrapperNodePath = path.join(path.dirname(process.execPath), `./resources/app/versions/${QQVersion}/wrapper.node`);
|
||||
}
|
||||
const nativemodule: any = { exports: {} };
|
||||
const nativemodule: { exports: WrapperNodeApi } = { exports: {} as WrapperNodeApi };
|
||||
process.dlopen(nativemodule, wrapperNodePath);
|
||||
return nativemodule.exports;
|
||||
}
|
||||
@@ -74,7 +74,7 @@ export function getMajorPath(QQVersion: string): string {
|
||||
}
|
||||
let majorPath = path.resolve(appPath, 'major.node');
|
||||
if (!fs.existsSync(majorPath)) {
|
||||
majorPath = path.join(appPath, `./resources/app/major.node`);
|
||||
majorPath = path.join(appPath, './resources/app/major.node');
|
||||
}
|
||||
//老版本兼容 未来去掉
|
||||
if (!fs.existsSync(majorPath)) {
|
||||
@@ -177,7 +177,7 @@ export class NapCatCore {
|
||||
profileListener.onSelfStatusChanged = (Info: SelfStatusInfo) => {
|
||||
if (Info.status == 20) {
|
||||
this.selfInfo.online = false;
|
||||
this.context.logger.log("账号状态变更为离线");
|
||||
this.context.logger.log('账号状态变更为离线');
|
||||
} else {
|
||||
this.selfInfo.online = true;
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { LRUCache } from "@/common/lru-cache";
|
||||
import crypto, { createHash } from "crypto";
|
||||
import { OidbPacket, PacketHexStr } from "@/core/packet/transformer/base";
|
||||
import { LogStack } from "@/core/packet/context/clientContext";
|
||||
import { NapCoreContext } from "@/core/packet/context/napCoreContext";
|
||||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||||
import { LRUCache } from '@/common/lru-cache';
|
||||
import crypto, { createHash } from 'crypto';
|
||||
import { OidbPacket, PacketHexStr } from '@/core/packet/transformer/base';
|
||||
import { LogStack } from '@/core/packet/context/clientContext';
|
||||
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
|
||||
export interface RecvPacket {
|
||||
type: string, // 仅recv
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import { createHash } from "crypto";
|
||||
import path, { dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import fs from "fs";
|
||||
import { IPacketClient } from "@/core/packet/client/baseClient";
|
||||
import { constants } from "node:os";
|
||||
import { LRUCache } from "@/common/lru-cache";
|
||||
import { LogStack } from "@/core/packet/context/clientContext";
|
||||
import { NapCoreContext } from "@/core/packet/context/napCoreContext";
|
||||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||||
import { createHash } from 'crypto';
|
||||
import path, { dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import fs from 'fs';
|
||||
import { IPacketClient } from '@/core/packet/client/baseClient';
|
||||
import { constants } from 'node:os';
|
||||
import { LRUCache } from '@/common/lru-cache';
|
||||
import { LogStack } from '@/core/packet/context/clientContext';
|
||||
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
|
||||
// 0 send 1 recv
|
||||
export interface NativePacketExportType {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { Data, WebSocket, ErrorEvent } from "ws";
|
||||
import { IPacketClient, RecvPacket } from "@/core/packet/client/baseClient";
|
||||
import { LogStack } from "@/core/packet/context/clientContext";
|
||||
import { NapCoreContext } from "@/core/packet/context/napCoreContext";
|
||||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||||
import { Data, WebSocket, ErrorEvent } from 'ws';
|
||||
import { IPacketClient, RecvPacket } from '@/core/packet/client/baseClient';
|
||||
import { LogStack } from '@/core/packet/context/clientContext';
|
||||
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
|
||||
export class WsPacketClient extends IPacketClient {
|
||||
private websocket: WebSocket | null = null;
|
||||
@@ -23,7 +23,7 @@ export class WsPacketClient extends IPacketClient {
|
||||
|
||||
check(): boolean {
|
||||
if (!this.napcore.config.packetServer) {
|
||||
this.logStack.pushLogWarn(`wsPacketClient 未配置服务器地址`);
|
||||
this.logStack.pushLogWarn('wsPacketClient 未配置服务器地址');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -52,7 +52,7 @@ export class WsPacketClient extends IPacketClient {
|
||||
try {
|
||||
await this.connect();
|
||||
return;
|
||||
} catch (error) {
|
||||
} catch {
|
||||
this.reconnectAttempts++;
|
||||
this.logStack.pushLogWarn(`第 ${this.reconnectAttempts}/${this.maxReconnectAttempts} 次尝试重连失败!`);
|
||||
await this.delay(5000);
|
||||
@@ -80,7 +80,7 @@ export class WsPacketClient extends IPacketClient {
|
||||
};
|
||||
this.websocket.onclose = () => {
|
||||
this.available = false;
|
||||
this.logger.warn(`WebSocket 连接关闭,尝试重连...`);
|
||||
this.logger.warn('WebSocket 连接关闭,尝试重连...');
|
||||
reject(new Error('WebSocket 连接关闭'));
|
||||
};
|
||||
this.websocket.onmessage = (event) => this.handleMessage(event.data).catch(err => {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { PacketContext } from "@/core/packet/context/packetContext";
|
||||
import { NapCatCore } from "@/core";
|
||||
import { PacketContext } from '@/core/packet/context/packetContext';
|
||||
import { NapCatCore } from '@/core';
|
||||
|
||||
export class PacketClientSession {
|
||||
private readonly context: PacketContext;
|
||||
|
@@ -1,15 +1,15 @@
|
||||
import { IPacketClient } from "@/core/packet/client/baseClient";
|
||||
import { NativePacketClient } from "@/core/packet/client/nativeClient";
|
||||
import { WsPacketClient } from "@/core/packet/client/wsClient";
|
||||
import { OidbPacket } from "@/core/packet/transformer/base";
|
||||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||||
import { NapCoreContext } from "@/core/packet/context/napCoreContext";
|
||||
import { IPacketClient } from '@/core/packet/client/baseClient';
|
||||
import { NativePacketClient } from '@/core/packet/client/nativeClient';
|
||||
import { WsPacketClient } from '@/core/packet/client/wsClient';
|
||||
import { OidbPacket } from '@/core/packet/transformer/base';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
|
||||
|
||||
type clientPriority = {
|
||||
type clientPriorityType = {
|
||||
[key: number]: (napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) => IPacketClient;
|
||||
}
|
||||
|
||||
const clientPriority: clientPriority = {
|
||||
const clientPriority: clientPriorityType = {
|
||||
10: (napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) => new NativePacketClient(napCore, logger, logStack),
|
||||
1: (napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) => new WsPacketClient(napCore, logger, logStack),
|
||||
};
|
||||
@@ -77,22 +77,22 @@ export class PacketClientContext {
|
||||
|
||||
async sendOidbPacket<T extends boolean = false>(pkt: OidbPacket, rsp?: T): Promise<T extends true ? Buffer : void> {
|
||||
const raw = await this._client.sendOidbPacket(pkt, rsp);
|
||||
return (rsp ? Buffer.from(raw.hex_data, "hex") : undefined) as T extends true ? Buffer : void;
|
||||
return (rsp ? Buffer.from(raw.hex_data, 'hex') : undefined) as T extends true ? Buffer : void;
|
||||
}
|
||||
|
||||
private newClient(): IPacketClient {
|
||||
const prefer = this.napCore.config.packetBackend;
|
||||
let client: IPacketClient | null;
|
||||
switch (prefer) {
|
||||
case "native":
|
||||
this.logger.info("使用指定的 NativePacketClient 作为后端");
|
||||
case 'native':
|
||||
this.logger.info('使用指定的 NativePacketClient 作为后端');
|
||||
client = new NativePacketClient(this.napCore, this.logger, this.logStack);
|
||||
break;
|
||||
case "frida":
|
||||
this.logger.info("[Core] [Packet] 使用指定的 FridaPacketClient 作为后端");
|
||||
case 'frida':
|
||||
this.logger.info('[Core] [Packet] 使用指定的 FridaPacketClient 作为后端');
|
||||
client = new WsPacketClient(this.napCore, this.logger, this.logStack);
|
||||
break;
|
||||
case "auto":
|
||||
case 'auto':
|
||||
case undefined:
|
||||
client = this.judgeClient();
|
||||
break;
|
||||
@@ -101,10 +101,10 @@ export class PacketClientContext {
|
||||
client = null;
|
||||
}
|
||||
if (!client?.check()) {
|
||||
throw new Error("[Core] [Packet] 无可用的后端,NapCat.Packet将不会加载!");
|
||||
throw new Error('[Core] [Packet] 无可用的后端,NapCat.Packet将不会加载!');
|
||||
}
|
||||
if (!client) {
|
||||
throw new Error("[Core] [Packet] 后端异常,NapCat.Packet将不会加载!");
|
||||
throw new Error('[Core] [Packet] 后端异常,NapCat.Packet将不会加载!');
|
||||
}
|
||||
return client;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ export class PacketClientContext {
|
||||
.sort((a, b) => b.score - a.score);
|
||||
const selectedClient = sortedClients[0]?.client;
|
||||
if (!selectedClient) {
|
||||
throw new Error("[Core] [Packet] 无可用的后端,NapCat.Packet将不会加载!");
|
||||
throw new Error('[Core] [Packet] 无可用的后端,NapCat.Packet将不会加载!');
|
||||
}
|
||||
this.logger.info(`自动选择 ${selectedClient.constructor.name} 作为后端`);
|
||||
return selectedClient;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { LogLevel, LogWrapper } from "@/common/log";
|
||||
import { NapCoreContext } from "@/core/packet/context/napCoreContext";
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { LogLevel, LogWrapper } from '@/common/log';
|
||||
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
|
||||
|
||||
// TODO: check bind?
|
||||
export class PacketLogger {
|
||||
@@ -10,7 +11,7 @@ export class PacketLogger {
|
||||
}
|
||||
|
||||
private _log(level: LogLevel, ...msg: any[]): void {
|
||||
this.napLogger._log(level, "[Core] [Packet] " + msg);
|
||||
this.napLogger._log(level, '[Core] [Packet] ' + msg);
|
||||
}
|
||||
|
||||
debug(...msg: any[]): void {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { NapCatCore } from "@/core";
|
||||
import { NapCatCore } from '@/core';
|
||||
|
||||
export interface NapCoreCompatBasicInfo {
|
||||
readonly uin: number;
|
||||
|
@@ -1,20 +1,20 @@
|
||||
import * as crypto from 'crypto';
|
||||
import { PacketContext } from "@/core/packet/context/packetContext";
|
||||
import * as trans from "@/core/packet/transformer";
|
||||
import { PacketMsg } from "@/core/packet/message/message";
|
||||
import { PacketContext } from '@/core/packet/context/packetContext';
|
||||
import * as trans from '@/core/packet/transformer';
|
||||
import { PacketMsg } from '@/core/packet/message/message';
|
||||
import {
|
||||
PacketMsgFileElement,
|
||||
PacketMsgPicElement,
|
||||
PacketMsgPttElement,
|
||||
PacketMsgVideoElement
|
||||
} from "@/core/packet/message/element";
|
||||
import { ChatType } from "@/core";
|
||||
import { MiniAppRawData, MiniAppReqParams } from "@/core/packet/entities/miniApp";
|
||||
import { AIVoiceChatType } from "@/core/packet/entities/aiChat";
|
||||
import { NapProtoDecodeStructType, NapProtoEncodeStructType } from "@napneko/nap-proto-core";
|
||||
import { IndexNode, MsgInfo } from "@/core/packet/transformer/proto";
|
||||
import { OidbPacket } from "@/core/packet/transformer/base";
|
||||
import { ImageOcrResult } from "@/core/packet/entities/ocrResult";
|
||||
} from '@/core/packet/message/element';
|
||||
import { ChatType } from '@/core';
|
||||
import { MiniAppRawData, MiniAppReqParams } from '@/core/packet/entities/miniApp';
|
||||
import { AIVoiceChatType } from '@/core/packet/entities/aiChat';
|
||||
import { NapProtoDecodeStructType, NapProtoEncodeStructType } from '@napneko/nap-proto-core';
|
||||
import { IndexNode, MsgInfo } from '@/core/packet/transformer/proto';
|
||||
import { OidbPacket } from '@/core/packet/transformer/base';
|
||||
import { ImageOcrResult } from '@/core/packet/entities/ocrResult';
|
||||
|
||||
export class PacketOperationContext {
|
||||
private readonly context: PacketContext;
|
||||
@@ -61,7 +61,7 @@ export class PacketOperationContext {
|
||||
}
|
||||
status = Number((extBigInt & 0xff00n) + ((extBigInt >> 16n) & 0xffn));
|
||||
return { status: 10, ext_status: status };
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { PacketHighwayContext } from "@/core/packet/highway/highwayContext";
|
||||
import { NapCatCore } from "@/core";
|
||||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||||
import { NapCoreContext } from "@/core/packet/context/napCoreContext";
|
||||
import { PacketClientContext } from "@/core/packet/context/clientContext";
|
||||
import { PacketOperationContext } from "@/core/packet/context/operationContext";
|
||||
import { PacketMsgConverter } from "@/core/packet/message/converter";
|
||||
import { PacketHighwayContext } from '@/core/packet/highway/highwayContext';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
|
||||
import { PacketClientContext } from '@/core/packet/context/clientContext';
|
||||
import { PacketOperationContext } from '@/core/packet/context/operationContext';
|
||||
import { PacketMsgConverter } from '@/core/packet/message/converter';
|
||||
|
||||
export class PacketContext {
|
||||
readonly msgConverter: PacketMsgConverter;
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as stream from 'node:stream';
|
||||
import { ReadStream } from "node:fs";
|
||||
import { HighwayTcpUploader } from "@/core/packet/highway/uploader/highwayTcpUploader";
|
||||
import { HighwayHttpUploader } from "@/core/packet/highway/uploader/highwayHttpUploader";
|
||||
import { PacketHighwaySig } from "@/core/packet/highway/highwayContext";
|
||||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||||
import { ReadStream } from 'node:fs';
|
||||
import { HighwayTcpUploader } from '@/core/packet/highway/uploader/highwayTcpUploader';
|
||||
import { HighwayHttpUploader } from '@/core/packet/highway/uploader/highwayHttpUploader';
|
||||
import { PacketHighwaySig } from '@/core/packet/highway/highwayContext';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
|
||||
export interface PacketHighwayTrans {
|
||||
uin: string;
|
||||
@@ -27,7 +27,8 @@ export class PacketHighwayClient {
|
||||
port: number = 80;
|
||||
logger: PacketLogger;
|
||||
|
||||
constructor(sig: PacketHighwaySig, logger: PacketLogger, server: string = 'htdata3.qq.com', port: number = 80) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
constructor(sig: PacketHighwaySig, logger: PacketLogger, _server: string = 'htdata3.qq.com', _port: number = 80) {
|
||||
this.sig = sig;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import assert from "node:assert";
|
||||
import assert from 'node:assert';
|
||||
|
||||
export class Frame{
|
||||
static pack(head: Buffer, body: Buffer): Buffer {
|
||||
|
@@ -1,22 +1,22 @@
|
||||
import { PacketHighwayClient } from "@/core/packet/highway/client";
|
||||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||||
import FetchSessionKey from "@/core/packet/transformer/highway/FetchSessionKey";
|
||||
import { int32ip2str, oidbIpv4s2HighwayIpv4s } from "@/core/packet/highway/utils";
|
||||
import { PacketHighwayClient } from '@/core/packet/highway/client';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
import FetchSessionKey from '@/core/packet/transformer/highway/FetchSessionKey';
|
||||
import { int32ip2str, oidbIpv4s2HighwayIpv4s } from '@/core/packet/highway/utils';
|
||||
import {
|
||||
PacketMsgFileElement,
|
||||
PacketMsgPicElement,
|
||||
PacketMsgPttElement,
|
||||
PacketMsgVideoElement
|
||||
} from "@/core/packet/message/element";
|
||||
import { ChatType, Peer } from "@/core";
|
||||
import { calculateSha1, calculateSha1StreamBytes, computeMd5AndLengthWithLimit } from "@/core/packet/utils/crypto/hash";
|
||||
import UploadGroupImage from "@/core/packet/transformer/highway/UploadGroupImage";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import * as trans from "@/core/packet/transformer";
|
||||
import fs from "fs";
|
||||
import { NapCoreContext } from "@/core/packet/context/napCoreContext";
|
||||
import { PacketClientContext } from "@/core/packet/context/clientContext";
|
||||
} from '@/core/packet/message/element';
|
||||
import { ChatType, Peer } from '@/core';
|
||||
import { calculateSha1, calculateSha1StreamBytes, computeMd5AndLengthWithLimit } from '@/core/packet/utils/crypto/hash';
|
||||
import UploadGroupImage from '@/core/packet/transformer/highway/UploadGroupImage';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import * as trans from '@/core/packet/transformer';
|
||||
import fs from 'fs';
|
||||
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
|
||||
import { PacketClientContext } from '@/core/packet/context/clientContext';
|
||||
|
||||
export const BlockSize = 1024 * 1024;
|
||||
|
||||
@@ -142,7 +142,7 @@ export class PacketHighwayContext {
|
||||
const resp = await this.client.sendOidbPacket(req, true);
|
||||
const preRespData = UploadGroupImage.parse(resp);
|
||||
const ukey = preRespData.upload.uKey;
|
||||
if (ukey && ukey != "") {
|
||||
if (ukey && ukey != '') {
|
||||
this.logger.debug(`[Highway] uploadGroupImageReq get upload ukey: ${ukey}, need upload!`);
|
||||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||||
const sha1 = Buffer.from(index.info.fileSha1, 'hex');
|
||||
@@ -179,7 +179,7 @@ export class PacketHighwayContext {
|
||||
const resp = await this.client.sendOidbPacket(req, true);
|
||||
const preRespData = trans.UploadPrivateImage.parse(resp);
|
||||
const ukey = preRespData.upload.uKey;
|
||||
if (ukey && ukey != "") {
|
||||
if (ukey && ukey != '') {
|
||||
this.logger.debug(`[Highway] uploadC2CImageReq get upload ukey: ${ukey}, need upload!`);
|
||||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||||
const sha1 = Buffer.from(index.info.fileSha1, 'hex');
|
||||
@@ -210,14 +210,14 @@ export class PacketHighwayContext {
|
||||
}
|
||||
|
||||
private async uploadGroupVideo(groupUin: number, video: PacketMsgVideoElement): Promise<void> {
|
||||
if (!video.filePath || !video.thumbPath) throw new Error("video.filePath or video.thumbPath is empty");
|
||||
if (!video.filePath || !video.thumbPath) throw new Error('video.filePath or video.thumbPath is empty');
|
||||
video.fileSha1 = Buffer.from(await calculateSha1(video.filePath)).toString('hex');
|
||||
video.thumbSha1 = Buffer.from(await calculateSha1(video.thumbPath)).toString('hex');
|
||||
const req = trans.UploadGroupVideo.build(groupUin, video);
|
||||
const resp = await this.client.sendOidbPacket(req, true);
|
||||
const preRespData = trans.UploadGroupVideo.parse(resp);
|
||||
const ukey = preRespData.upload.uKey;
|
||||
if (ukey && ukey != "") {
|
||||
if (ukey && ukey != '') {
|
||||
this.logger.debug(`[Highway] uploadGroupVideoReq get upload video ukey: ${ukey}, need upload!`);
|
||||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||||
@@ -244,7 +244,7 @@ export class PacketHighwayContext {
|
||||
this.logger.debug(`[Highway] uploadGroupVideoReq get upload invalid ukey ${ukey}, don't need upload!`);
|
||||
}
|
||||
const subFile = preRespData.upload.subFileInfos[0];
|
||||
if (subFile.uKey && subFile.uKey != "") {
|
||||
if (subFile.uKey && subFile.uKey != '') {
|
||||
this.logger.debug(`[Highway] uploadGroupVideoReq get upload video thumb ukey: ${subFile.uKey}, need upload!`);
|
||||
const index = preRespData.upload.msgInfo.msgInfoBody[1].index;
|
||||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||||
@@ -275,14 +275,14 @@ export class PacketHighwayContext {
|
||||
}
|
||||
|
||||
private async uploadC2CVideo(peerUid: string, video: PacketMsgVideoElement): Promise<void> {
|
||||
if (!video.filePath || !video.thumbPath) throw new Error("video.filePath or video.thumbPath is empty");
|
||||
if (!video.filePath || !video.thumbPath) throw new Error('video.filePath or video.thumbPath is empty');
|
||||
video.fileSha1 = Buffer.from(await calculateSha1(video.filePath)).toString('hex');
|
||||
video.thumbSha1 = Buffer.from(await calculateSha1(video.thumbPath)).toString('hex');
|
||||
const req = trans.UploadPrivateVideo.build(peerUid, video);
|
||||
const resp = await this.client.sendOidbPacket(req, true);
|
||||
const preRespData = trans.UploadPrivateVideo.parse(resp);
|
||||
const ukey = preRespData.upload.uKey;
|
||||
if (ukey && ukey != "") {
|
||||
if (ukey && ukey != '') {
|
||||
this.logger.debug(`[Highway] uploadC2CVideoReq get upload video ukey: ${ukey}, need upload!`);
|
||||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||||
@@ -309,7 +309,7 @@ export class PacketHighwayContext {
|
||||
this.logger.debug(`[Highway] uploadC2CVideoReq get upload invalid ukey ${ukey}, don't need upload!`);
|
||||
}
|
||||
const subFile = preRespData.upload.subFileInfos[0];
|
||||
if (subFile.uKey && subFile.uKey != "") {
|
||||
if (subFile.uKey && subFile.uKey != '') {
|
||||
this.logger.debug(`[Highway] uploadC2CVideoReq get upload video thumb ukey: ${subFile.uKey}, need upload!`);
|
||||
const index = preRespData.upload.msgInfo.msgInfoBody[1].index;
|
||||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||||
@@ -345,7 +345,7 @@ export class PacketHighwayContext {
|
||||
const resp = await this.client.sendOidbPacket(req, true);
|
||||
const preRespData = trans.UploadGroupPtt.parse(resp);
|
||||
const ukey = preRespData.upload.uKey;
|
||||
if (ukey && ukey != "") {
|
||||
if (ukey && ukey != '') {
|
||||
this.logger.debug(`[Highway] uploadGroupPttReq get upload ptt ukey: ${ukey}, need upload!`);
|
||||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||||
@@ -381,7 +381,7 @@ export class PacketHighwayContext {
|
||||
const resp = await this.client.sendOidbPacket(req, true);
|
||||
const preRespData = trans.UploadPrivatePtt.parse(resp);
|
||||
const ukey = preRespData.upload.uKey;
|
||||
if (ukey && ukey != "") {
|
||||
if (ukey && ukey != '') {
|
||||
this.logger.debug(`[Highway] uploadC2CPttReq get upload ptt ukey: ${ukey}, need upload!`);
|
||||
const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
|
||||
const md5 = Buffer.from(index.info.fileHash, 'hex');
|
||||
@@ -419,7 +419,7 @@ export class PacketHighwayContext {
|
||||
const resp = await this.client.sendOidbPacket(req, true);
|
||||
const preRespData = trans.UploadGroupFile.parse(resp);
|
||||
if (!preRespData?.upload?.boolFileExist) {
|
||||
this.logger.debug(`[Highway] uploadGroupFileReq file not exist, need upload!`);
|
||||
this.logger.debug('[Highway] uploadGroupFileReq file not exist, need upload!');
|
||||
const ext = new NapProtoMsg(proto.FileUploadExt).encode({
|
||||
unknown1: 100,
|
||||
unknown2: 1,
|
||||
@@ -439,9 +439,9 @@ export class PacketHighwayContext {
|
||||
},
|
||||
clientInfo: {
|
||||
clientType: 3,
|
||||
appId: "100",
|
||||
appId: '100',
|
||||
terminalType: 3,
|
||||
clientVer: "1.1.1",
|
||||
clientVer: '1.1.1',
|
||||
unknown: 4
|
||||
},
|
||||
fileNameInfo: {
|
||||
@@ -469,7 +469,7 @@ export class PacketHighwayContext {
|
||||
ext
|
||||
);
|
||||
} else {
|
||||
this.logger.debug(`[Highway] uploadGroupFileReq file exist, don't need upload!`);
|
||||
this.logger.debug('[Highway] uploadGroupFileReq file exist, don\'t need upload!');
|
||||
}
|
||||
file.fileUuid = preRespData.upload.fileId;
|
||||
}
|
||||
@@ -482,7 +482,7 @@ export class PacketHighwayContext {
|
||||
const res = await this.client.sendOidbPacket(req, true);
|
||||
const preRespData = trans.UploadPrivateFile.parse(res);
|
||||
if (!preRespData.upload?.boolFileExist) {
|
||||
this.logger.debug(`[Highway] uploadC2CFileReq file not exist, need upload!`);
|
||||
this.logger.debug('[Highway] uploadC2CFileReq file not exist, need upload!');
|
||||
const ext = new NapProtoMsg(proto.FileUploadExt).encode({
|
||||
unknown1: 100,
|
||||
unknown2: 1,
|
||||
@@ -500,9 +500,9 @@ export class PacketHighwayContext {
|
||||
},
|
||||
clientInfo: {
|
||||
clientType: 3,
|
||||
appId: "100",
|
||||
appId: '100',
|
||||
terminalType: 3,
|
||||
clientVer: "1.1.1",
|
||||
clientVer: '1.1.1',
|
||||
unknown: 4
|
||||
},
|
||||
fileNameInfo: {
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import crypto from "node:crypto";
|
||||
import http from "node:http";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { IHighwayUploader } from "@/core/packet/highway/uploader/highwayUploader";
|
||||
import { Frame } from "@/core/packet/highway/frame";
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import crypto from 'node:crypto';
|
||||
import http from 'node:http';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { IHighwayUploader } from '@/core/packet/highway/uploader/highwayUploader';
|
||||
import { Frame } from '@/core/packet/highway/frame';
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
|
||||
export class HighwayHttpUploader extends IHighwayUploader {
|
||||
async upload(): Promise<void> {
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import net from "node:net";
|
||||
import stream from "node:stream";
|
||||
import crypto from "node:crypto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { BlockSize } from "@/core/packet/highway/highwayContext";
|
||||
import { Frame } from "@/core/packet/highway/frame";
|
||||
import { IHighwayUploader } from "@/core/packet/highway/uploader/highwayUploader";
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import net from 'node:net';
|
||||
import stream from 'node:stream';
|
||||
import crypto from 'node:crypto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { BlockSize } from '@/core/packet/highway/highwayContext';
|
||||
import { Frame } from '@/core/packet/highway/frame';
|
||||
import { IHighwayUploader } from '@/core/packet/highway/uploader/highwayUploader';
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
|
||||
class HighwayTcpUploaderTransform extends stream.Transform {
|
||||
uploader: HighwayTcpUploader;
|
||||
@@ -17,7 +17,8 @@ class HighwayTcpUploaderTransform extends stream.Transform {
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
_transform(data: Buffer, _: BufferEncoding, callback: stream.TransformCallback) {
|
||||
// eslint-disable-next-line no-undef
|
||||
override _transform(data: Buffer, _: BufferEncoding, callback: stream.TransformCallback) {
|
||||
let chunkOffset = 0;
|
||||
while (chunkOffset < data.length) {
|
||||
const chunkSize = Math.min(BlockSize, data.length - chunkOffset);
|
||||
@@ -60,6 +61,7 @@ export class HighwayTcpUploader extends IHighwayUploader {
|
||||
socket.end();
|
||||
reject(new Error('Upload aborted due to timeout'));
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [head, _] = Frame.unpack(chunk);
|
||||
handleRspHeader(head);
|
||||
});
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import * as tea from "@/core/packet/utils/crypto/tea";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { PacketHighwayTrans } from "@/core/packet/highway/client";
|
||||
import { PacketLogger } from "@/core/packet/context/loggerContext";
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import * as tea from '@/core/packet/utils/crypto/tea';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { PacketHighwayTrans } from '@/core/packet/highway/client';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
|
||||
export abstract class IHighwayUploader {
|
||||
readonly trans: PacketHighwayTrans;
|
||||
@@ -32,7 +32,7 @@ export abstract class IHighwayUploader {
|
||||
msgBaseHead: {
|
||||
version: 1,
|
||||
uin: this.trans.uin,
|
||||
command: "PicUp.DataUp",
|
||||
command: 'PicUp.DataUp',
|
||||
seq: 0,
|
||||
retryTimes: 0,
|
||||
appId: 1600001604,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { NapProtoEncodeStructType } from "@napneko/nap-proto-core";
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoEncodeStructType } from '@napneko/nap-proto-core';
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
|
||||
|
||||
export const int32ip2str = (ip: number) => {
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import * as crypto from "crypto";
|
||||
import { PushMsgBody } from "@/core/packet/transformer/proto";
|
||||
import { NapProtoEncodeStructType } from "@napneko/nap-proto-core";
|
||||
import { PacketMsg, PacketSendMsgElement } from "@/core/packet/message/message";
|
||||
import { IPacketMsgElement, PacketMsgTextElement } from "@/core/packet/message/element";
|
||||
import { SendTextElement } from "@/core";
|
||||
import * as crypto from 'crypto';
|
||||
import { PushMsgBody } from '@/core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType } from '@napneko/nap-proto-core';
|
||||
import { PacketMsg, PacketSendMsgElement } from '@/core/packet/message/message';
|
||||
import { IPacketMsgElement, PacketMsgTextElement } from '@/core/packet/message/element';
|
||||
import { SendTextElement } from '@/core';
|
||||
|
||||
export class PacketMsgBuilder {
|
||||
protected static failBackText = new PacketMsgTextElement(
|
||||
{
|
||||
textElement: { content: "[该消息类型暂不支持查看]" }
|
||||
textElement: { content: '[该消息类型暂不支持查看]' }
|
||||
} as SendTextElement
|
||||
);
|
||||
|
||||
@@ -24,7 +24,7 @@ export class PacketMsgBuilder {
|
||||
}
|
||||
return {
|
||||
responseHead: {
|
||||
fromUid: "",
|
||||
fromUid: '',
|
||||
fromUin: node.senderUin,
|
||||
toUid: node.groupId ? undefined : selfUid,
|
||||
forward: node.groupId ? undefined : {
|
||||
|
@@ -15,7 +15,7 @@ import {
|
||||
SendStructLongMsgElement,
|
||||
SendTextElement,
|
||||
SendVideoElement
|
||||
} from "@/core";
|
||||
} from '@/core';
|
||||
import {
|
||||
IPacketMsgElement,
|
||||
PacketMsgAtElement,
|
||||
@@ -30,8 +30,8 @@ import {
|
||||
PacketMsgTextElement,
|
||||
PacketMsgVideoElement,
|
||||
PacketMultiMsgElement
|
||||
} from "@/core/packet/message/element";
|
||||
import { PacketMsg, PacketSendMsgElement } from "@/core/packet/message/message";
|
||||
} from '@/core/packet/message/element';
|
||||
import { PacketMsg, PacketSendMsgElement } from '@/core/packet/message/message';
|
||||
|
||||
const SupportedElementTypes = [
|
||||
ElementType.TEXT,
|
||||
@@ -146,7 +146,7 @@ export class PacketMsgConverter {
|
||||
? msg.sendMemberName
|
||||
: msg.sendNickName && msg.sendNickName !== ''
|
||||
? msg.sendNickName
|
||||
: "QQ用户",
|
||||
: 'QQ用户',
|
||||
time: +msg.msgTime,
|
||||
msg: msg.elements.map((element) => {
|
||||
if (!this.isValidElementType(element.elementType)) return null;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as zlib from "node:zlib";
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import * as zlib from 'node:zlib';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import {
|
||||
CustomFace,
|
||||
Elem,
|
||||
@@ -12,9 +12,8 @@ import {
|
||||
OidbSvcTrpcTcp0XE37_800Response,
|
||||
FileExtra,
|
||||
GroupFileExtra
|
||||
} from "@/core/packet/transformer/proto";
|
||||
} from '@/core/packet/transformer/proto';
|
||||
import {
|
||||
BaseEmojiType,
|
||||
FaceType,
|
||||
NTMsgAtType,
|
||||
PicType,
|
||||
@@ -29,14 +28,15 @@ import {
|
||||
SendStructLongMsgElement,
|
||||
SendTextElement,
|
||||
SendVideoElement
|
||||
} from "@/core";
|
||||
import { ForwardMsgBuilder } from "@/common/forward-msg-builder";
|
||||
import { PacketMsg, PacketSendMsgElement } from "@/core/packet/message/message";
|
||||
} from '@/core';
|
||||
import { ForwardMsgBuilder } from '@/common/forward-msg-builder';
|
||||
import { PacketMsg, PacketSendMsgElement } from '@/core/packet/message/message';
|
||||
|
||||
// raw <-> packet
|
||||
// TODO: SendStructLongMsgElement
|
||||
export abstract class IPacketMsgElement<T extends PacketSendMsgElement> {
|
||||
protected constructor(rawElement: T) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected constructor(_rawElement: T) {
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
@@ -64,7 +64,7 @@ export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> {
|
||||
this.text = element.textElement.content;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
text: {
|
||||
str: this.text
|
||||
@@ -72,7 +72,7 @@ export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> {
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
override toPreview(): string {
|
||||
return this.text;
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ export class PacketMsgAtElement extends PacketMsgTextElement {
|
||||
this.atAll = element.textElement.atType === NTMsgAtType.ATTYPEALL;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
text: {
|
||||
str: this.text,
|
||||
@@ -127,7 +127,7 @@ export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
|
||||
return this.messageClientSeq === 0;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
srcMsg: {
|
||||
origSeqs: [this.isGroupReply ? this.messageClientSeq : this.messageSeq],
|
||||
@@ -152,8 +152,8 @@ export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
return "[回复消息]";
|
||||
override toPreview(): string {
|
||||
return '[回复消息]';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,18 +169,18 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
|
||||
this.isLargeFace = element.faceElement.faceType === FaceType.AniSticke;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
if (this.isLargeFace) {
|
||||
return [{
|
||||
commonElem: {
|
||||
serviceType: 37,
|
||||
pbElem: new NapProtoMsg(QBigFaceExtra).encode({
|
||||
aniStickerPackId: "1",
|
||||
aniStickerId: "8",
|
||||
aniStickerPackId: '1',
|
||||
aniStickerId: '8',
|
||||
faceId: this.faceId,
|
||||
sourceType: 1,
|
||||
resultId: this.resultId,
|
||||
preview: "",
|
||||
preview: '',
|
||||
randomType: 1
|
||||
}),
|
||||
businessType: 1
|
||||
@@ -198,8 +198,8 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
|
||||
serviceType: 33,
|
||||
pbElem: new NapProtoMsg(QSmallFaceExtra).encode({
|
||||
faceId: this.faceId,
|
||||
preview: "",
|
||||
preview2: ""
|
||||
preview: '',
|
||||
preview2: ''
|
||||
}),
|
||||
businessType: 1
|
||||
}
|
||||
@@ -207,8 +207,8 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
|
||||
}
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
return "[表情]";
|
||||
override toPreview(): string {
|
||||
return '[表情]';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ export class PacketMsgMarkFaceElement extends IPacketMsgElement<SendMarketFaceEl
|
||||
this.emojiKey = element.marketFaceElement.key;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
marketFace: {
|
||||
faceName: this.emojiName,
|
||||
@@ -245,7 +245,7 @@ export class PacketMsgMarkFaceElement extends IPacketMsgElement<SendMarketFaceEl
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
override toPreview(): string {
|
||||
return `${this.emojiName}`;
|
||||
}
|
||||
}
|
||||
@@ -280,11 +280,11 @@ export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
|
||||
) : element.picElement.summary;
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
override get valid(): boolean {
|
||||
return !!this.msgInfo;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
if (!this.msgInfo) return [];
|
||||
return [{
|
||||
commonElem: {
|
||||
@@ -295,7 +295,7 @@ export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
override toPreview(): string {
|
||||
return this.summary;
|
||||
}
|
||||
}
|
||||
@@ -318,18 +318,18 @@ export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> {
|
||||
this.fileSize = element.videoElement.fileSize;
|
||||
this.filePath = element.videoElement.filePath;
|
||||
this.thumbSize = element.videoElement.thumbSize;
|
||||
this.thumbPath = element.videoElement.thumbPath?.get(0);
|
||||
this.thumbPath = element.videoElement.thumbPath?.get(0) as string | undefined;
|
||||
this.fileMd5 = element.videoElement.videoMd5;
|
||||
this.thumbMd5 = element.videoElement.thumbMd5;
|
||||
this.thumbWidth = element.videoElement.thumbWidth;
|
||||
this.thumbHeight = element.videoElement.thumbHeight;
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
override get valid(): boolean {
|
||||
return !!this.msgInfo;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
if (!this.msgInfo) return [];
|
||||
return [{
|
||||
commonElem: {
|
||||
@@ -340,8 +340,8 @@ export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> {
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
return "[视频]";
|
||||
override toPreview(): string {
|
||||
return '[视频]';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,11 +361,11 @@ export class PacketMsgPttElement extends IPacketMsgElement<SendPttElement> {
|
||||
this.fileDuration = Math.round(element.pttElement.duration); // TODO: cc
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
override get valid(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [];
|
||||
// if (!this.msgInfo) return [];
|
||||
// return [{
|
||||
@@ -377,8 +377,8 @@ export class PacketMsgPttElement extends IPacketMsgElement<SendPttElement> {
|
||||
// }];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
return "[语音]";
|
||||
override toPreview(): string {
|
||||
return '[语音]';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,11 +402,11 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
|
||||
this.fileSize = +element.fileElement.fileSize;
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
override get valid(): boolean {
|
||||
return this.isGroupFile || Boolean(this._e37_800_rsp);
|
||||
}
|
||||
|
||||
buildContent(): Uint8Array | undefined {
|
||||
override buildContent(): Uint8Array | undefined {
|
||||
if (this.isGroupFile || !this._e37_800_rsp) return undefined;
|
||||
return new NapProtoMsg(FileExtra).encode({
|
||||
file: {
|
||||
@@ -437,7 +437,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
|
||||
});
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
if (!this.isGroupFile) return [];
|
||||
const lb = Buffer.alloc(2);
|
||||
const transElemVal = new NapProtoMsg(GroupFileExtra).encode({
|
||||
@@ -450,7 +450,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
|
||||
fileSize: BigInt(this.fileSize),
|
||||
fileName: this.fileName,
|
||||
fileSha: this.fileSha1,
|
||||
extInfoString: "",
|
||||
extInfoString: '',
|
||||
fileMd5: this.fileMd5,
|
||||
}
|
||||
}
|
||||
@@ -464,7 +464,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
override toPreview(): string {
|
||||
return `[文件]${this.fileName}`;
|
||||
}
|
||||
}
|
||||
@@ -477,7 +477,7 @@ export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement>
|
||||
this.payload = element.arkElement.bytesData;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
lightAppElem: {
|
||||
data: Buffer.concat([
|
||||
@@ -488,8 +488,8 @@ export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement>
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
return "[卡片消息]";
|
||||
override toPreview(): string {
|
||||
return '[卡片消息]';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +501,7 @@ export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElem
|
||||
this.content = element.markdownElement.content;
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
commonElem: {
|
||||
serviceType: 45,
|
||||
@@ -513,7 +513,7 @@ export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElem
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
override toPreview(): string {
|
||||
return `[Markdown消息 ${this.content}]`;
|
||||
}
|
||||
}
|
||||
@@ -528,7 +528,7 @@ export class PacketMultiMsgElement extends IPacketMsgElement<SendStructLongMsgEl
|
||||
this.message = message ?? [];
|
||||
}
|
||||
|
||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||
return [{
|
||||
lightAppElem: {
|
||||
data: Buffer.concat([
|
||||
@@ -539,7 +539,7 @@ export class PacketMultiMsgElement extends IPacketMsgElement<SendStructLongMsgEl
|
||||
}];
|
||||
}
|
||||
|
||||
toPreview(): string {
|
||||
return "[聊天记录]";
|
||||
override toPreview(): string {
|
||||
return '[聊天记录]';
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { IPacketMsgElement } from "@/core/packet/message/element";
|
||||
import { SendMessageElement, SendStructLongMsgElement } from "@/core";
|
||||
import { IPacketMsgElement } from '@/core/packet/message/element';
|
||||
import { SendMessageElement, SendStructLongMsgElement } from '@/core';
|
||||
|
||||
export type PacketSendMsgElement = SendMessageElement | SendStructLongMsgElement
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import { AIVoiceChatType } from "@/core/packet/entities/aiChat";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import { AIVoiceChatType } from '@/core/packet/entities/aiChat';
|
||||
|
||||
class FetchAiVoiceList extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0X929D_0Resp> {
|
||||
constructor() {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import { AIVoiceChatType } from "@/core/packet/entities/aiChat";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import { AIVoiceChatType } from '@/core/packet/entities/aiChat';
|
||||
|
||||
class GetAiVoice extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0X929B_0Resp> {
|
||||
constructor() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import { MiniAppReqParams } from "@/core/packet/entities/miniApp";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import { MiniAppReqParams } from '@/core/packet/entities/miniApp';
|
||||
|
||||
class GetMiniAppAdaptShareInfo extends PacketTransformer<typeof proto.MiniAppAdaptShareInfoResp> {
|
||||
constructor() {
|
||||
@@ -23,24 +23,24 @@ class GetMiniAppAdaptShareInfo extends PacketTransformer<typeof proto.MiniAppAda
|
||||
templateType: req.templateType,
|
||||
businessType: req.businessType,
|
||||
picUrl: req.picUrl,
|
||||
vidUrl: "",
|
||||
vidUrl: '',
|
||||
jumpUrl: req.jumpUrl,
|
||||
iconUrl: req.iconUrl,
|
||||
verType: req.verType,
|
||||
shareType: req.shareType,
|
||||
versionId: req.versionId,
|
||||
withShareTicket: req.withShareTicket,
|
||||
webURL: req.webUrl ?? "",
|
||||
webURL: req.webUrl ?? '',
|
||||
appidRich: Buffer.alloc(0),
|
||||
template: {
|
||||
templateId: "",
|
||||
templateData: ""
|
||||
templateId: '',
|
||||
templateData: ''
|
||||
},
|
||||
field20: ""
|
||||
field20: ''
|
||||
}
|
||||
});
|
||||
return {
|
||||
cmd: "LightAppSvc.mini_app_share.AdaptShareInfo",
|
||||
cmd: 'LightAppSvc.mini_app_share.AdaptShareInfo',
|
||||
data: PacketHexStrBuilder(data)
|
||||
};
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class GetStrangerInfo extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XFE1_2RSP> {
|
||||
constructor() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class GroupSign extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
|
||||
constructor() {
|
||||
@@ -14,7 +14,7 @@ class GroupSign extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
|
||||
body: {
|
||||
uin: String(uin),
|
||||
groupUin: String(groupCode),
|
||||
version: "9.0.90"
|
||||
version: '9.0.90'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class ImageOCR extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0xE07_0_Response> {
|
||||
constructor() {
|
||||
@@ -16,11 +16,11 @@ class ImageOCR extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0xE07_0_Resp
|
||||
entrance: 1,
|
||||
ocrReqBody: {
|
||||
imageUrl: url,
|
||||
originMd5: "",
|
||||
afterCompressMd5: "",
|
||||
afterCompressFileSize: "",
|
||||
afterCompressWeight: "",
|
||||
afterCompressHeight: "",
|
||||
originMd5: '',
|
||||
afterCompressMd5: '',
|
||||
afterCompressFileSize: '',
|
||||
afterCompressWeight: '',
|
||||
afterCompressHeight: '',
|
||||
isCut: false,
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class SendPoke extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
|
||||
constructor() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class SetSpecialTitle extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
|
||||
constructor() {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { NapProtoDecodeStructType } from "@napneko/nap-proto-core";
|
||||
import { PacketMsgBuilder } from "@/core/packet/message/builder";
|
||||
import { NapProtoDecodeStructType } from '@napneko/nap-proto-core';
|
||||
import { PacketMsgBuilder } from '@/core/packet/message/builder';
|
||||
|
||||
export type PacketHexStr = string & { readonly hexNya: unique symbol };
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class DownloadGroupFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0x6D6Response> {
|
||||
constructor() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class DownloadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
constructor() {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import { IndexNode } from "@/core/packet/transformer/proto";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoEncodeStructType, NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import { IndexNode } from '@/core/packet/transformer/proto';
|
||||
|
||||
class DownloadImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
constructor() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class DownloadOfflineFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37Response> {
|
||||
constructor() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
|
||||
class DownloadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37_1200Response> {
|
||||
constructor() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
|
||||
class FetchSessionKey extends PacketTransformer<typeof proto.HttpConn0x6ff_501Response> {
|
||||
constructor() {
|
||||
@@ -20,11 +20,11 @@ class FetchSessionKey extends PacketTransformer<typeof proto.HttpConn0x6ff_501Re
|
||||
field9: 2,
|
||||
field10: 9,
|
||||
field11: 8,
|
||||
ver: "1.0.1"
|
||||
ver: '1.0.1'
|
||||
}
|
||||
});
|
||||
return {
|
||||
cmd: "HttpConn.0x6ff_501",
|
||||
cmd: 'HttpConn.0x6ff_501',
|
||||
data: PacketHexStrBuilder(req)
|
||||
};
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import { PacketMsgFileElement } from "@/core/packet/message/element";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import { PacketMsgFileElement } from '@/core/packet/message/element';
|
||||
|
||||
class UploadGroupFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0x6D6Response> {
|
||||
constructor() {
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import crypto from "node:crypto";
|
||||
import { PacketMsgPicElement } from "@/core/packet/message/element";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgPicElement } from '@/core/packet/message/element';
|
||||
|
||||
class UploadGroupImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
constructor() {
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import crypto from "node:crypto";
|
||||
import { PacketMsgPttElement } from "@/core/packet/message/element";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgPttElement } from '@/core/packet/message/element';
|
||||
|
||||
class UploadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
constructor() {
|
||||
@@ -57,7 +57,7 @@ class UploadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
compatQMsgSceneType: 2,
|
||||
extBizInfo: {
|
||||
pic: {
|
||||
textSummary: "Nya~",
|
||||
textSummary: 'Nya~',
|
||||
},
|
||||
video: {
|
||||
bytesPbReserve: Buffer.alloc(0),
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import crypto from "node:crypto";
|
||||
import { PacketMsgVideoElement } from "@/core/packet/message/element";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgVideoElement } from '@/core/packet/message/element';
|
||||
|
||||
class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
constructor() {
|
||||
@@ -11,7 +11,7 @@ class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp>
|
||||
}
|
||||
|
||||
build(groupUin: number, video: PacketMsgVideoElement): OidbPacket {
|
||||
if (!video.fileSize || !video.thumbSize) throw new Error("video.fileSize or video.thumbSize is empty");
|
||||
if (!video.fileSize || !video.thumbSize) throw new Error('video.fileSize or video.thumbSize is empty');
|
||||
const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
@@ -37,7 +37,7 @@ class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp>
|
||||
fileSize: +video.fileSize,
|
||||
fileHash: video.fileMd5,
|
||||
fileSha1: video.fileSha1,
|
||||
fileName: "nya.mp4",
|
||||
fileName: 'nya.mp4',
|
||||
type: {
|
||||
type: 2,
|
||||
picFormat: 0,
|
||||
@@ -55,7 +55,7 @@ class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp>
|
||||
fileSize: +video.thumbSize,
|
||||
fileHash: video.thumbMd5,
|
||||
fileSha1: video.thumbSha1,
|
||||
fileName: "nya.jpg",
|
||||
fileName: 'nya.jpg',
|
||||
type: {
|
||||
type: 1,
|
||||
picFormat: 0,
|
||||
@@ -77,7 +77,7 @@ class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp>
|
||||
extBizInfo: {
|
||||
pic: {
|
||||
bizType: 0,
|
||||
textSummary: "Nya~",
|
||||
textSummary: 'Nya~',
|
||||
},
|
||||
video: {
|
||||
bytesPbReserve: Buffer.from([0x80, 0x01, 0x00]),
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import { PacketMsgFileElement } from "@/core/packet/message/element";
|
||||
import { computeMd5AndLengthWithLimit } from "@/core/packet/utils/crypto/hash";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import { PacketMsgFileElement } from '@/core/packet/message/element';
|
||||
import { computeMd5AndLengthWithLimit } from '@/core/packet/utils/crypto/hash';
|
||||
|
||||
class UploadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37Response> {
|
||||
constructor() {
|
||||
@@ -21,7 +21,7 @@ class UploadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE
|
||||
fileName: file.fileName,
|
||||
md510MCheckSum: await computeMd5AndLengthWithLimit(file.filePath, 10 * 1024 * 1024),
|
||||
sha1CheckSum: file.fileSha1,
|
||||
localPath: "/",
|
||||
localPath: '/',
|
||||
md5CheckSum: file.fileMd5,
|
||||
sha3CheckSum: Buffer.alloc(0)
|
||||
},
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import crypto from "node:crypto";
|
||||
import { PacketMsgPicElement } from "@/core/packet/message/element";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgPicElement } from '@/core/packet/message/element';
|
||||
|
||||
class UploadPrivateImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
constructor() {
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import crypto from "node:crypto";
|
||||
import { PacketMsgPttElement } from "@/core/packet/message/element";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgPttElement } from '@/core/packet/message/element';
|
||||
|
||||
class UploadPrivatePtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
constructor() {
|
||||
@@ -58,7 +58,7 @@ class UploadPrivatePtt extends PacketTransformer<typeof proto.NTV2RichMediaResp>
|
||||
compatQMsgSceneType: 1,
|
||||
extBizInfo: {
|
||||
pic: {
|
||||
textSummary: "Nya~",
|
||||
textSummary: 'Nya~',
|
||||
},
|
||||
ptt: {
|
||||
bytesReserve: Buffer.from([0x08, 0x00, 0x38, 0x00]),
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import OidbBase from "@/core/packet/transformer/oidb/oidbBase";
|
||||
import crypto from "node:crypto";
|
||||
import { PacketMsgVideoElement } from "@/core/packet/message/element";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
|
||||
import crypto from 'node:crypto';
|
||||
import { PacketMsgVideoElement } from '@/core/packet/message/element';
|
||||
|
||||
class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
|
||||
constructor() {
|
||||
@@ -11,7 +11,7 @@ class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaRes
|
||||
}
|
||||
|
||||
build(peerUin: string, video: PacketMsgVideoElement): OidbPacket {
|
||||
if (!video.fileSize || !video.thumbSize) throw new Error("video.fileSize or video.thumbSize is empty");
|
||||
if (!video.fileSize || !video.thumbSize) throw new Error('video.fileSize or video.thumbSize is empty');
|
||||
const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
|
||||
reqHead: {
|
||||
common: {
|
||||
@@ -38,7 +38,7 @@ class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaRes
|
||||
fileSize: +video.fileSize,
|
||||
fileHash: video.fileMd5,
|
||||
fileSha1: video.fileSha1,
|
||||
fileName: "nya.mp4",
|
||||
fileName: 'nya.mp4',
|
||||
type: {
|
||||
type: 2,
|
||||
picFormat: 0,
|
||||
@@ -56,7 +56,7 @@ class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaRes
|
||||
fileSize: +video.thumbSize,
|
||||
fileHash: video.thumbMd5,
|
||||
fileSha1: video.thumbSha1,
|
||||
fileName: "nya.jpg",
|
||||
fileName: 'nya.jpg',
|
||||
type: {
|
||||
type: 1,
|
||||
picFormat: 0,
|
||||
@@ -78,7 +78,7 @@ class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaRes
|
||||
extBizInfo: {
|
||||
pic: {
|
||||
bizType: 0,
|
||||
textSummary: "Nya~",
|
||||
textSummary: 'Nya~',
|
||||
},
|
||||
video: {
|
||||
bytesPbReserve: Buffer.from([0x80, 0x01, 0x00]),
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import zlib from "node:zlib";
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import { PacketMsg } from "@/core/packet/message/message";
|
||||
import zlib from 'node:zlib';
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
import { PacketMsg } from '@/core/packet/message/message';
|
||||
|
||||
class UploadForwardMsg extends PacketTransformer<typeof proto.SendLongMsgResp> {
|
||||
constructor() {
|
||||
@@ -14,7 +14,7 @@ class UploadForwardMsg extends PacketTransformer<typeof proto.SendLongMsgResp> {
|
||||
const longMsgResultData = new NapProtoMsg(proto.LongMsgResult).encode(
|
||||
{
|
||||
action: {
|
||||
actionCommand: "MultiMsg",
|
||||
actionCommand: 'MultiMsg',
|
||||
actionData: {
|
||||
msgBody: msgBody
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class UploadForwardMsg extends PacketTransformer<typeof proto.SendLongMsgResp> {
|
||||
}
|
||||
);
|
||||
return {
|
||||
cmd: "trpc.group.long_msg_interface.MsgService.SsoSendLongMsg",
|
||||
cmd: 'trpc.group.long_msg_interface.MsgService.SsoSendLongMsg',
|
||||
data: PacketHexStrBuilder(req)
|
||||
};
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as proto from "@/core/packet/transformer/proto";
|
||||
import { NapProtoMsg } from "@napneko/nap-proto-core";
|
||||
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from "@/core/packet/transformer/base";
|
||||
import * as proto from '@/core/packet/transformer/proto';
|
||||
import { NapProtoMsg } from '@napneko/nap-proto-core';
|
||||
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from '@/core/packet/transformer/base';
|
||||
|
||||
class OidbBase extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
|
||||
constructor() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { ScalarType } from "@protobuf-ts/runtime";
|
||||
import { ProtoField } from "@napneko/nap-proto-core";
|
||||
import { ContentHead, MessageBody, MessageControl, RoutingHead } from "@/core/packet/transformer/proto";
|
||||
import { ScalarType } from '@protobuf-ts/runtime';
|
||||
import { ProtoField } from '@napneko/nap-proto-core';
|
||||
import { ContentHead, MessageBody, MessageControl, RoutingHead } from '@/core/packet/transformer/proto';
|
||||
|
||||
export const FaceRoamRequest = {
|
||||
comm: ProtoField(1, () => PlatInfo, true),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const MiniAppAdaptShareInfoReq = {
|
||||
appId: ProtoField(2, ScalarType.STRING),
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { MsgInfoBody } from "@/core/packet/transformer/proto";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
import { MsgInfoBody } from '@/core/packet/transformer/proto';
|
||||
|
||||
export const DataHighwayHead = {
|
||||
version: ProtoField(1, ScalarType.UINT32),
|
||||
|
@@ -1,32 +1,32 @@
|
||||
// action folder
|
||||
export * from "./action/action";
|
||||
export * from "./action/miniAppAdaptShareInfo";
|
||||
export * from './action/action';
|
||||
export * from './action/miniAppAdaptShareInfo';
|
||||
|
||||
// highway folder
|
||||
export * from "./highway/highway";
|
||||
export * from './highway/highway';
|
||||
|
||||
// message folder
|
||||
export * from "./message/action";
|
||||
export * from "./message/c2c";
|
||||
export * from "./message/component";
|
||||
export * from "./message/element";
|
||||
export * from "./message/group";
|
||||
export * from "./message/message";
|
||||
export * from "./message/notify";
|
||||
export * from "./message/routing";
|
||||
export * from './message/action';
|
||||
export * from './message/c2c';
|
||||
export * from './message/component';
|
||||
export * from './message/element';
|
||||
export * from './message/group';
|
||||
export * from './message/message';
|
||||
export * from './message/notify';
|
||||
export * from './message/routing';
|
||||
|
||||
// oidb folder
|
||||
export * from "./oidb/common/Ntv2.RichMediaReq";
|
||||
export * from "./oidb/common/Ntv2.RichMediaResp";
|
||||
export * from "./oidb/Oidb.0x6D6";
|
||||
export * from "./oidb/Oidb.0x8FC_2";
|
||||
export * from "./oidb/Oidb.0x9067_202";
|
||||
export * from "./oidb/Oidb.0x929";
|
||||
export * from "./oidb/Oidb.0xE37_1200";
|
||||
export * from "./oidb/Oidb.0xE37_1700";
|
||||
export * from "./oidb/Oidb.0XE37_800";
|
||||
export * from "./oidb/Oidb.0xEB7";
|
||||
export * from "./oidb/Oidb.0xED3_1";
|
||||
export * from "./oidb/Oidb.0XFE1_2";
|
||||
export * from "./oidb/OidbBase";
|
||||
export * from "./oidb/Oidb.0xE07";
|
||||
export * from './oidb/common/Ntv2.RichMediaReq';
|
||||
export * from './oidb/common/Ntv2.RichMediaResp';
|
||||
export * from './oidb/Oidb.0x6D6';
|
||||
export * from './oidb/Oidb.0x8FC_2';
|
||||
export * from './oidb/Oidb.0x9067_202';
|
||||
export * from './oidb/Oidb.0x929';
|
||||
export * from './oidb/Oidb.0xE37_1200';
|
||||
export * from './oidb/Oidb.0xE37_1700';
|
||||
export * from './oidb/Oidb.0XE37_800';
|
||||
export * from './oidb/Oidb.0xEB7';
|
||||
export * from './oidb/Oidb.0xED3_1';
|
||||
export * from './oidb/Oidb.0XFE1_2';
|
||||
export * from './oidb/OidbBase';
|
||||
export * from './oidb/Oidb.0xE07';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { PushMsgBody } from "@/core/packet/transformer/proto";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
import { PushMsgBody } from '@/core/packet/transformer/proto';
|
||||
|
||||
export const LongMsgResult = {
|
||||
action: ProtoField(2, () => LongMsgAction)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const C2C = {
|
||||
uin: ProtoField(1, ScalarType.UINT32, true),
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { Elem } from "@/core/packet/transformer/proto";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
import { Elem } from '@/core/packet/transformer/proto';
|
||||
|
||||
export const Attr = {
|
||||
codePage: ProtoField(1, ScalarType.INT32),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const Elem = {
|
||||
text: ProtoField(1, () => Text, true),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const GroupRecallMsg = {
|
||||
type: ProtoField(1, ScalarType.UINT32),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const GroupAdminExtra = {
|
||||
adminUid: ProtoField(1, ScalarType.STRING),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
import {
|
||||
C2C,
|
||||
ForwardHead,
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
ResponseGrp, RichText,
|
||||
Trans0X211,
|
||||
WPATmp
|
||||
} from "@/core/packet/transformer/proto";
|
||||
} from '@/core/packet/transformer/proto';
|
||||
|
||||
export const ContentHead = {
|
||||
type: ProtoField(1, ScalarType.UINT32),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const FriendRecall = {
|
||||
info: ProtoField(1, () => FriendRecallInfo),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const ForwardHead = {
|
||||
field1: ProtoField(1, ScalarType.UINT32, true),
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { OidbSvcTrpcTcp0XE37_800_1200Metadata } from "@/core/packet/transformer/proto";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
import { OidbSvcTrpcTcp0XE37_800_1200Metadata } from '@/core/packet/transformer/proto';
|
||||
|
||||
export const OidbSvcTrpcTcp0XE37_800 = {
|
||||
subCommand: ProtoField(1, ScalarType.UINT32),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const OidbSvcTrpcTcp0XFE1_2 = {
|
||||
uin: ProtoField(1, ScalarType.UINT32),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ProtoField, ScalarType } from "@napneko/nap-proto-core";
|
||||
import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
|
||||
|
||||
export const OidbSvcTrpcTcp0x6D6 = {
|
||||
file: ProtoField(1, () => OidbSvcTrpcTcp0x6D6Upload, true),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user