Merge pull request #749 from NapNeko/type-force

style: Type force
This commit is contained in:
手瓜一十雪
2025-02-03 11:13:55 +08:00
committed by GitHub
276 changed files with 1546 additions and 1483 deletions

View File

@@ -12,7 +12,7 @@ insert_final_newline = true
# Set default charset # Set default charset
charset = utf-8 charset = utf-8
# 2 space indentation # 4 space indentation
[*.{cjs,mjs,js,jsx,ts,tsx,css,scss,sass,html,json}] [*.{cjs,mjs,js,jsx,ts,tsx,css,scss,sass,html,json}]
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
@@ -21,4 +21,4 @@ indent_size = 4
charset = latin1 charset = latin1
# Unfortunately, EditorConfig doesn't support space configuration inside import braces directly. # Unfortunately, EditorConfig doesn't support space configuration inside import braces directly.
# You'll need to rely on your linter/formatter like ESLint or Prettier for that. # You'll need to rely on your linter/formatter like ESLint or Prettier for that.

View File

@@ -1,70 +1,32 @@
import typescriptEslint from "@typescript-eslint/eslint-plugin"; import eslint from '@eslint/js';
import _import from "eslint-plugin-import"; import tsEslintPlugin from '@typescript-eslint/eslint-plugin';
import { fixupPluginRules } from "@eslint/compat"; import tsEslintParser from '@typescript-eslint/parser';
import globals from "globals"; 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 customTsFlatConfig = [
const dirname = path.dirname(filename); {
const compat = new FlatCompat({ name: 'typescript-eslint/base',
baseDirectory: dirname, languageOptions: {
recommendedConfig: js.configs.recommended, parser: tsEslintParser,
allConfig: js.configs.all sourceType: 'module',
}); globals: {
...globals.browser,
export default [{ ...globals.node,
ignores: ["src/core/proto/"], NodeJS: 'readonly', // 添加 NodeJS 全局变量
}, ...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,
}, },
}, },
}, files: ['**/*.{ts,tsx}'],
rules: {
rules: { ...tsEslintPlugin.configs.recommended.rules,
indent: ["error", 4], 'quotes': ['error', 'single'], // 使用单引号
semi: ["error", "always"], 'semi': ['error', 'always'], // 强制使用分号
"no-unused-vars": "off", 'indent': ['error', 4], // 使用 4 空格缩进
"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,
}, },
ecmaVersion: 5, plugins: {
sourceType: "commonjs", '@typescript-eslint': tsEslintPlugin,
},
ignores: ['src/webui/**'], // 忽略 src/webui/ 目录所有文件
}, },
}]; ];
export default [eslint.configs.recommended, ...customTsFlatConfig];

View File

@@ -164,7 +164,7 @@ interface CommonExt {
address: string address: string
regTime: number regTime: number
interest: string interest: string
labels: unknown[] labels: string[]
qqLevel: QQLevel qqLevel: QQLevel
} }

View File

@@ -1,4 +1,4 @@
import { encode } from "silk-wasm"; import { encode } from 'silk-wasm';
export interface EncodeArgs { export interface EncodeArgs {
input: ArrayBufferView | ArrayBuffer input: ArrayBufferView | ArrayBuffer

View File

@@ -4,8 +4,8 @@ import path from 'node:path';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
import { EncodeResult, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm'; import { EncodeResult, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
import { LogWrapper } from '@/common/log'; import { LogWrapper } from '@/common/log';
import { EncodeArgs } from "@/common/audio-worker"; import { EncodeArgs } from '@/common/audio-worker';
import { FFmpegService } from "@/common/ffmpeg"; import { FFmpegService } from '@/common/ffmpeg';
const ALLOW_SAMPLE_RATE = [8000, 12000, 16000, 24000, 32000, 44100, 48000]; 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( async function handleWavFile(
file: Buffer, file: Buffer,
filePath: string, filePath: string,
pcmPath: string, pcmPath: string
logger: LogWrapper
): Promise<{ input: Buffer; sampleRate: number }> { ): Promise<{ input: Buffer; sampleRate: number }> {
const { fmt } = getWavFileInfo(file); const { fmt } = getWavFileInfo(file);
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) { 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 }; 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`); logger.log(`语音文件${filePath}需要转换成silk`);
const pcmPath = `${pttPath}.pcm`; const pcmPath = `${pttPath}.pcm`;
const { input, sampleRate } = isWav(file) const { input, sampleRate } = isWav(file)
? (await handleWavFile(file, filePath, pcmPath, logger)) ? (await handleWavFile(file, filePath, pcmPath))
: { input: await FFmpegService.convert(filePath, pcmPath, logger), sampleRate: 24000 }; : { input: await FFmpegService.convert(filePath, pcmPath), sampleRate: 24000 };
const silk = await piscina.run({ input: input, sampleRate: sampleRate }); const silk = await piscina.run({ input: input, sampleRate: sampleRate });
await fsPromise.writeFile(pttPath, Buffer.from(silk.data)); await fsPromise.writeFile(pttPath, Buffer.from(silk.data));
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration); logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
@@ -59,8 +58,8 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
let duration = 0; let duration = 0;
try { try {
duration = getDuration(file) / 1000; duration = getDuration(file) / 1000;
} catch (e: any) { } catch (e: unknown) {
logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, e.stack); logger.log('获取语音文件时长失败, 使用文件大小推测时长', filePath, (e as Error).stack);
duration = await guessDuration(filePath, logger); duration = await guessDuration(filePath, logger);
} }
return { return {
@@ -69,8 +68,8 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
duration, duration,
}; };
} }
} catch (error: any) { } catch (error: unknown) {
logger.logError('convert silk failed', error.stack); logger.logError('convert silk failed', (error as Error).stack);
return {}; return {};
} }
} }

View File

@@ -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 type TaskExecutor<T> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void, onCancel: (callback: () => void) => void) => void | Promise<void>;
export class CancelableTask<T> { export class CancelableTask<T> {
@@ -7,30 +8,34 @@ export class CancelableTask<T> {
private cancelListeners: Array<() => void> = []; private cancelListeners: Array<() => void> = [];
constructor(executor: TaskExecutor<T>) { constructor(executor: TaskExecutor<T>) {
this.promise = new Promise<T>(async (resolve, reject) => { this.promise = new Promise<T>((resolve, reject) => {
const onCancel = (callback: () => void) => { const onCancel = (callback: () => void) => {
this.cancelCallback = callback; this.cancelCallback = callback;
}; };
try { const execute = async () => {
await executor( try {
(value) => { await executor(
if (!this.isCanceled) { (value) => {
resolve(value); if (!this.isCanceled) {
} resolve(value);
}, }
(reason) => { },
if (!this.isCanceled) { (reason) => {
reject(reason); if (!this.isCanceled) {
} reject(reason);
}, }
onCancel },
); onCancel
} catch (error) { );
if (!this.isCanceled) { } catch (error) {
reject(error); if (!this.isCanceled) {
reject(error);
}
} }
} };
execute();
}); });
} }
@@ -72,41 +77,4 @@ export class CancelableTask<T> {
next: () => this.promise.then(value => ({ value, done: true })), next: () => this.promise.then(value => ({ value, done: true })),
}; };
} }
}
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);
}
} }

View File

@@ -39,9 +39,9 @@ export abstract class ConfigBase<T> {
if (!fs.existsSync(configPath) && copy_default) { if (!fs.existsSync(configPath) && copy_default) {
try { try {
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8')); fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
this.core.context.logger.log(`[Core] [Config] 配置文件创建成功!\n`); this.core.context.logger.log('[Core] [Config] 配置文件创建成功!\n');
} catch (e: any) { } catch (e: unknown) {
this.core.context.logger.logError(`[Core] [Config] 创建配置文件时发生错误:`, e.message); this.core.context.logger.logError('[Core] [Config] 创建配置文件时发生错误:', (e as Error).message);
} }
} else if (!fs.existsSync(configPath) && !copy_default) { } else if (!fs.existsSync(configPath) && !copy_default) {
fs.writeFileSync(configPath, '{}'); fs.writeFileSync(configPath, '{}');
@@ -50,11 +50,11 @@ export abstract class ConfigBase<T> {
this.configData = json5.parse(fs.readFileSync(configPath, 'utf-8')); this.configData = json5.parse(fs.readFileSync(configPath, 'utf-8'));
this.core.context.logger.logDebug(`[Core] [Config] 配置文件${configPath}加载`, this.configData); this.core.context.logger.logDebug(`[Core] [Config] 配置文件${configPath}加载`, this.configData);
return this.configData; return this.configData;
} catch (e: any) { } catch (e: unknown) {
if (e instanceof SyntaxError) { if (e instanceof SyntaxError) {
this.core.context.logger.logError(`[Core] [Config] 配置文件格式错误,请检查配置文件:`, e.message); this.core.context.logger.logError('[Core] [Config] 配置文件格式错误,请检查配置文件:', e.message);
} else { } else {
this.core.context.logger.logError(`[Core] [Config] 读取配置文件时发生错误:`, e.message); this.core.context.logger.logError('[Core] [Config] 读取配置文件时发生错误:', (e as Error).message);
} }
return {} as T; return {} as T;
} }
@@ -67,8 +67,8 @@ export abstract class ConfigBase<T> {
const configPath = this.getConfigPath(selfInfo.uin); const configPath = this.getConfigPath(selfInfo.uin);
try { try {
fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2)); fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2));
} catch (e: any) { } catch (e: unknown) {
this.core.context.logger.logError(`保存配置文件 ${configPath} 时发生错误:`, e.message); this.core.context.logger.logError(`保存配置文件 ${configPath} 时发生错误:`, (e as Error).message);
} }
} }
} }

View File

@@ -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;
}
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { NodeIQQNTWrapperSession } from '@/core/wrapper'; import { NodeIQQNTWrapperSession } from '@/core/wrapper';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
import { ListenerNamingMapping, ServiceNamingMapping } from '@/core'; import { ListenerNamingMapping, ServiceNamingMapping } from '@/core';
@@ -60,17 +61,22 @@ export class NTEventWrapper {
[key: string]: () => { [key: string]: (...params: Parameters<T>) => Promise<ReturnType<T>> }; [key: string]: () => { [key: string]: (...params: Parameters<T>) => Promise<ReturnType<T>> };
}; };
if (eventNameArr.length > 1) { if (eventNameArr.length > 1) {
const serviceName = 'get' + eventNameArr[0].replace('NodeIKernel', ''); const serviceName = 'get' + (eventNameArr[0]?.replace('NodeIKernel', '') ?? '');
const eventName = eventNameArr[1]; 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]; let event = services[eventName];
//重新绑定this //重新绑定this
event = event.bind(services); event = event?.bind(services);
if (event) { if (event) {
return event as T; return event as T;
} }
return undefined; return undefined;
} }
return undefined;
} }
createListenerFunction<T>(listenerMainName: string, uniqueCode: string = ''): T { createListenerFunction<T>(listenerMainName: string, uniqueCode: string = ''): T {
@@ -126,8 +132,8 @@ export class NTEventWrapper {
) { ) {
return new Promise<Parameters<ListenerType>>((resolve, reject) => { return new Promise<Parameters<ListenerType>>((resolve, reject) => {
const ListenerNameList = listenerAndMethod.split('/'); const ListenerNameList = listenerAndMethod.split('/');
const ListenerMainName = ListenerNameList[0]; const ListenerMainName = ListenerNameList[0] ?? '';
const ListenerSubName = ListenerNameList[1]; const ListenerSubName = ListenerNameList[1] ?? '';
const id = randomUUID(); const id = randomUUID();
let complete = 0; let complete = 0;
let retData: Parameters<ListenerType> | undefined = undefined; let retData: Parameters<ListenerType> | undefined = undefined;
@@ -205,8 +211,8 @@ export class NTEventWrapper {
} }
const ListenerNameList = listenerAndMethod.split('/'); const ListenerNameList = listenerAndMethod.split('/');
const ListenerMainName = ListenerNameList[0]; const ListenerMainName = ListenerNameList[0]??'';
const ListenerSubName = ListenerNameList[1]; const ListenerSubName = ListenerNameList[1]??'';
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>( return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
(resolve, reject) => { (resolve, reject) => {

View File

@@ -1,18 +1,18 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { FFmpeg } from '@ffmpeg.wasm/main'; import { FFmpeg } from '@ffmpeg.wasm/main';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
import { readFileSync, statSync, writeFileSync } from 'fs'; import { readFileSync, statSync, writeFileSync } from 'fs';
import type { LogWrapper } from './log';
import type { VideoInfo } from './video'; import type { VideoInfo } from './video';
import { fileTypeFromFile } from 'file-type'; import { fileTypeFromFile } from 'file-type';
import imageSize from 'image-size'; import imageSize from 'image-size';
class FFmpegService { class FFmpegService {
public static async extractThumbnail(videoPath: string, thumbnailPath: string): Promise<void> { public static async extractThumbnail(videoPath: string, thumbnailPath: string): Promise<void> {
const ffmpegInstance = await FFmpeg.create({ core: '@ffmpeg.wasm/core-mt' }); const ffmpegInstance = await FFmpeg.create({ core: '@ffmpeg.wasm/core-mt' });
const videoFileName = `${randomUUID()}.mp4`; const videoFileName = `${randomUUID()}.mp4`;
const outputFileName = `${randomUUID()}.jpg`; const outputFileName = `${randomUUID()}.jpg`;
try { try {
ffmpegInstance.fs.writeFile(videoFileName, readFileSync(videoPath)); 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) { if (code !== 0) {
throw new Error('Error extracting thumbnail: FFmpeg process exited with code ' + code); 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' 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, '-ar', '8000', '-b:a', '12.2k', outputFileName]
: ['-f', 's16le', '-ar', '24000', '-ac', '1', '-i', inputFileName, 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) { if (code !== 0) {
throw new Error('Error extracting thumbnail: FFmpeg process exited with code ' + code); throw new Error('Error extracting thumbnail: FFmpeg process exited with code ' + code);
} }
@@ -74,7 +74,7 @@ import imageSize from 'image-size';
try { try {
ffmpegInstance.fs.writeFile(inputFileName, readFileSync(filePath)); ffmpegInstance.fs.writeFile(inputFileName, readFileSync(filePath));
const params = ['-y', '-i', inputFileName, '-ar', '24000', '-ac', '1', '-f', 's16le', outputFileName]; 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) { if (code !== 0) {
throw new Error('FFmpeg process exited with code ' + code); throw new Error('FFmpeg process exited with code ' + code);
} }
@@ -96,27 +96,27 @@ import imageSize from 'image-size';
} }
} }
} }
public static async getVideoInfo(videoPath: string, thumbnailPath: string): Promise<VideoInfo> { public static async getVideoInfo(videoPath: string, thumbnailPath: string): Promise<VideoInfo> {
await FFmpegService.extractThumbnail(videoPath, thumbnailPath); await FFmpegService.extractThumbnail(videoPath, thumbnailPath);
let fileType = (await fileTypeFromFile(videoPath))?.ext ?? 'mp4'; const fileType = (await fileTypeFromFile(videoPath))?.ext ?? 'mp4';
const inputFileName = `${randomUUID()}.${fileType}`; const inputFileName = `${randomUUID()}.${fileType}`;
const ffmpegInstance = await FFmpeg.create({ core: '@ffmpeg.wasm/core-mt' }); const ffmpegInstance = await FFmpeg.create({ core: '@ffmpeg.wasm/core-mt' });
ffmpegInstance.fs.writeFile(inputFileName, readFileSync(videoPath)); ffmpegInstance.fs.writeFile(inputFileName, readFileSync(videoPath));
ffmpegInstance.setLogging(true); ffmpegInstance.setLogging(true);
let duration = 60; let duration = 60;
ffmpegInstance.setLogger((level, ...msg) => { ffmpegInstance.setLogger((_level, ...msg) => {
const message = msg.join(' '); const message = msg.join(' ');
const durationMatch = message.match(/Duration: (\d+):(\d+):(\d+\.\d+)/); const durationMatch = message.match(/Duration: (\d+):(\d+):(\d+\.\d+)/);
if (durationMatch) { if (durationMatch) {
const hours = parseInt(durationMatch[1], 10); const hours = parseInt(durationMatch[1] ?? '0', 10);
const minutes = parseInt(durationMatch[2], 10); const minutes = parseInt(durationMatch[2] ?? '0', 10);
const seconds = parseFloat(durationMatch[3]); const seconds = parseFloat(durationMatch[3] ?? '0');
duration = hours * 3600 + minutes * 60 + seconds; duration = hours * 3600 + minutes * 60 + seconds;
} }
}); });
await ffmpegInstance.run('-i', inputFileName); await ffmpegInstance.run('-i', inputFileName);
let image = imageSize(thumbnailPath); const image = imageSize(thumbnailPath);
ffmpegInstance.fs.unlink(inputFileName); ffmpegInstance.fs.unlink(inputFileName);
const fileSize = statSync(videoPath).size; const fileSize = statSync(videoPath).size;
return { return {
@@ -126,7 +126,7 @@ import imageSize from 'image-size';
format: fileType, format: fileType,
size: fileSize, size: fileSize,
filePath: videoPath filePath: videoPath
} };
} }
} }
type FFmpegMethod = 'extractThumbnail' | 'convertFile' | 'convert' | 'getVideoInfo'; type FFmpegMethod = 'extractThumbnail' | 'convertFile' | 'convert' | 'getVideoInfo';
@@ -137,15 +137,15 @@ interface FFmpegTask {
} }
export default async function handleFFmpegTask({ method, args }: FFmpegTask): Promise<any> { export default async function handleFFmpegTask({ method, args }: FFmpegTask): Promise<any> {
switch (method) { switch (method) {
case 'extractThumbnail': case 'extractThumbnail':
return await FFmpegService.extractThumbnail(...args as [string, string]); return await FFmpegService.extractThumbnail(...args as [string, string]);
case 'convertFile': case 'convertFile':
return await FFmpegService.convertFile(...args as [string, string, string]); return await FFmpegService.convertFile(...args as [string, string, string]);
case 'convert': case 'convert':
return await FFmpegService.convert(...args as [string, string]); return await FFmpegService.convert(...args as [string, string]);
case 'getVideoInfo': case 'getVideoInfo':
return await FFmpegService.getVideoInfo(...args as [string, string]); return await FFmpegService.getVideoInfo(...args as [string, string]);
default: default:
throw new Error(`Unknown method: ${method}`); throw new Error(`Unknown method: ${method}`);
} }
} }

View File

@@ -1,6 +1,6 @@
import Piscina from "piscina"; /* eslint-disable @typescript-eslint/no-explicit-any */
import { VideoInfo } from "./video"; import Piscina from 'piscina';
import type { LogWrapper } from "./log"; import { VideoInfo } from './video';
type EncodeArgs = { type EncodeArgs = {
method: 'extractThumbnail' | 'convertFile' | 'convert' | 'getVideoInfo'; method: 'extractThumbnail' | 'convertFile' | 'convert' | 'getVideoInfo';

View File

@@ -83,7 +83,7 @@ class FileUUIDManager {
this.cache = new TimeBasedCache<string, FileUUIDData>(5000, ttl); 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; const uuid = customUUID ? customUUID : randomUUID().replace(/-/g, '') + endString;
this.cache.put(uuid, data); this.cache.put(uuid, data);
return uuid; return uuid;
@@ -101,7 +101,7 @@ export class FileNapCatOneBotUUIDWrap {
this.manager = new FileUUIDManager(ttl); 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); return this.manager.encode({ peer, modelId, fileId, fileUUID }, endString, customUUID);
} }
@@ -109,8 +109,8 @@ export class FileNapCatOneBotUUIDWrap {
return this.manager.decode(uuid); return this.manager.decode(uuid);
} }
public encode(peer: Peer, msgId: string, elementId: string, fileUUID: string = "", customUUID?: string): string { public encode(peer: Peer, msgId: string, elementId: string, fileUUID: string = '', customUUID?: string): string {
return this.manager.encode({ peer, msgId, elementId, fileUUID }, "", customUUID); return this.manager.encode({ peer, msgId, elementId, fileUUID }, '', customUUID);
} }
public decode(uuid: string): FileUUIDData | undefined { public decode(uuid: string): FileUUIDData | undefined {

View File

@@ -58,8 +58,8 @@ function timeoutPromise(timeout: number, errorMsg: string): Promise<void> {
async function checkFile(path: string): Promise<void> { async function checkFile(path: string): Promise<void> {
try { try {
await stat(path); await stat(path);
} catch (error: any) { } catch (error: unknown) {
if (error.code === 'ENOENT') { if ((error as Error & { code: string }).code === 'ENOENT') {
// 如果文件不存在,则抛出一个错误 // 如果文件不存在,则抛出一个错误
throw new Error(`文件不存在: ${path}`); throw new Error(`文件不存在: ${path}`);
} else { } else {
@@ -169,6 +169,7 @@ export async function checkUriType(Uri: string) {
const data = uri.split(',')[1]; const data = uri.split(',')[1];
if (data) return { Uri: data, Type: FileUriType.Base64 }; if (data) return { Uri: data, Type: FileUriType.Base64 };
} }
return;
}, Uri); }, Uri);
if (OtherFileRet) return OtherFileRet; if (OtherFileRet) return OtherFileRet;
@@ -190,7 +191,7 @@ export async function uriToLocalFile(dir: string, uri: string, filename: string
} }
case FileUriType.Remote: { case FileUriType.Remote: {
const buffer = await httpDownload({ url: HandledUri, headers: headers }); const buffer = await httpDownload({ url: HandledUri, headers: headers ?? {} });
fs.writeFileSync(filePath, buffer); fs.writeFileSync(filePath, buffer);
return { success: true, errMsg: '', fileName: filename, path: filePath }; return { success: true, errMsg: '', fileName: filename, path: filePath };
} }

View File

@@ -1,5 +1,5 @@
import * as crypto from "node:crypto"; import * as crypto from 'node:crypto';
import { PacketMsg } from "@/core/packet/message/message"; import { PacketMsg } from '@/core/packet/message/message';
interface ForwardMsgJson { interface ForwardMsgJson {
app: string app: string
@@ -50,15 +50,15 @@ interface ForwardAdaptMsgElement {
} }
export class ForwardMsgBuilder { 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 id = crypto.randomUUID();
const isGroupMsg = msg.some(m => m.isGroupMsg); const isGroupMsg = msg.some(m => m.isGroupMsg);
if (!source) { 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) { if (!news) {
news = msg.length === 0 ? [{ 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 => ({ }] : msg.map(m => ({
text: `${m.senderName}: ${m.msg?.map(msg => msg.preview).join('')}`, text: `${m.senderName}: ${m.msg?.map(msg => msg.preview).join('')}`,
})); }));
@@ -67,15 +67,15 @@ export class ForwardMsgBuilder {
summary = `查看${msg.length}条转发消息`; summary = `查看${msg.length}条转发消息`;
} }
if (!prompt) { if (!prompt) {
prompt = "[聊天记录]"; prompt = '[聊天记录]';
} }
return { return {
app: "com.tencent.multimsg", app: 'com.tencent.multimsg',
config: { config: {
autosize: 1, autosize: 1,
forward: 1, forward: 1,
round: 1, round: 1,
type: "normal", type: 'normal',
width: 300 width: 300
}, },
desc: prompt, desc: prompt,
@@ -93,8 +93,8 @@ export class ForwardMsgBuilder {
} }
}, },
prompt, prompt,
ver: "0.0.0.5", ver: '0.0.0.5',
view: "contact", view: 'contact',
}; };
} }
@@ -102,12 +102,12 @@ export class ForwardMsgBuilder {
return this.build(resId, []); 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 => ({ return this.build(resId, packetMsg.map(msg => ({
senderName: msg.senderName, senderName: msg.senderName,
isGroupMsg: msg.groupId !== undefined, isGroupMsg: msg.groupId !== undefined,
msg: msg.msg.map(m => ({ msg: msg.msg.map(m => ({
preview: m.valid ? m.toPreview() : "[该消息类型暂不支持查看]", preview: m.valid ? m.toPreview() : '[该消息类型暂不支持查看]',
})) }))
})), source, news, summary, prompt); })), source, news, summary, prompt);
} }

View File

@@ -1,14 +1,16 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import path from 'node:path'; import path from 'node:path';
import fs from 'fs'; import fs from 'fs';
import os from 'node:os'; import os from 'node:os';
import { QQLevel } from '@/core'; 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> { 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) => { return new Promise<ReturnType<T> | undefined>((resolve) => {
try { try {
const result = func(...args); const result = func(...args);
resolve(result); resolve(result);
} catch (e) { } catch {
resolve(undefined); resolve(undefined);
} }
}); });
@@ -166,14 +168,14 @@ export function calcQQLevel(level?: QQLevel) {
} }
export function stringifyWithBigInt(obj: any) { export function stringifyWithBigInt(obj: any) {
return JSON.stringify(obj, (key, value) => return JSON.stringify(obj, (_key, value) =>
typeof value === 'bigint' ? value.toString() : value typeof value === 'bigint' ? value.toString() : value
); );
} }
export function parseAppidFromMajor(nodeMajor: string): string | undefined { export function parseAppidFromMajor(nodeMajor: string): string | undefined {
const hexSequence = "A4 09 00 00 00 35"; const hexSequence = 'A4 09 00 00 00 35';
const sequenceBytes = Buffer.from(hexSequence.replace(/ /g, ""), "hex"); const sequenceBytes = Buffer.from(hexSequence.replace(/ /g, ''), 'hex');
const filePath = path.resolve(nodeMajor); const filePath = path.resolve(nodeMajor);
const fileContent = fs.readFileSync(filePath); const fileContent = fs.readFileSync(filePath);
@@ -192,8 +194,8 @@ export function parseAppidFromMajor(nodeMajor: string): string | undefined {
const content = fileContent.subarray(start, end); const content = fileContent.subarray(start, end);
if (!content.every(byte => byte === 0x00)) { if (!content.every(byte => byte === 0x00)) {
try { try {
return content.toString("utf-8"); return content.toString('utf-8');
} catch (error) { } catch {
break; break;
} }
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import winston, { format, transports } from 'winston'; import winston, { format, transports } from 'winston';
import { truncateString } from '@/common/helper'; import { truncateString } from '@/common/helper';
import path from 'node:path'; import path from 'node:path';
@@ -34,7 +35,7 @@ class Subscription {
for (const history of Subscription.history) { for (const history of Subscription.history) {
try { try {
listener(history); listener(history);
} catch (_) { } catch {
// ignore // ignore
} }
} }
@@ -68,7 +69,7 @@ export class LogWrapper {
format: format.combine( format: format.combine(
format.timestamp({ format: 'MM-DD HH:mm:ss' }), format.timestamp({ format: 'MM-DD HH:mm:ss' }),
format.printf(({ timestamp, level, message, ...meta }) => { format.printf(({ timestamp, level, message, ...meta }) => {
const userInfo = meta.userInfo ? `${meta.userInfo} | ` : ''; const userInfo = meta['userInfo'] ? `${meta['userInfo']} | ` : '';
return `${timestamp} [${level}] ${userInfo}${message}`; return `${timestamp} [${level}] ${userInfo}${message}`;
}) })
), ),
@@ -83,7 +84,7 @@ export class LogWrapper {
format: format.combine( format: format.combine(
format.colorize(), format.colorize(),
format.printf(({ timestamp, level, message, ...meta }) => { format.printf(({ timestamp, level, message, ...meta }) => {
const userInfo = meta.userInfo ? `${meta.userInfo} | ` : ''; const userInfo = meta['userInfo'] ? `${meta['userInfo']} | ` : '';
return `${timestamp} [${level}] ${userInfo}${message}`; return `${timestamp} [${level}] ${userInfo}${message}`;
}) })
), ),
@@ -303,7 +304,7 @@ function textElementToText(textElement: any): string {
const originalContentLines = textElement.content.split('\n'); const originalContentLines = textElement.content.split('\n');
return `${originalContentLines[0]}${originalContentLines.length > 1 ? ' ...' : ''}`; return `${originalContentLines[0]}${originalContentLines.length > 1 ? ' ...' : ''}`;
} else if (textElement.atType === NTMsgAtType.ATTYPEALL) { } else if (textElement.atType === NTMsgAtType.ATTYPEALL) {
return `@全体成员`; return '@全体成员';
} else if (textElement.atType === NTMsgAtType.ATTYPEONE) { } else if (textElement.atType === NTMsgAtType.ATTYPEONE) {
return `${textElement.content} (${textElement.atUid})`; return `${textElement.content} (${textElement.atUid})`;
} }

View File

@@ -68,7 +68,10 @@ export class LimitedHashTable<K, V> {
const listSize = Math.min(size, keyList.length); const listSize = Math.min(size, keyList.length);
for (let i = 0; i < listSize; i++) { for (let i = 0; i < listSize; i++) {
const key = keyList[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; return result;
} }
@@ -96,8 +99,10 @@ class MessageUniqueWrapper {
createUniqueMsgId(peer: Peer, msgId: string) { createUniqueMsgId(peer: Peer, msgId: string) {
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`; const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
const hash = crypto.createHash('md5').update(key).digest(); const hash = crypto.createHash('md5').update(key).digest();
//设置第一个bit为0 保证shortId为正数 if (hash[0]) {
hash[0] &= 0x7f; //设置第一个bit为0 保证shortId为正数
hash[0] &= 0x7f;
}
const shortId = hash.readInt32BE(0); const shortId = hash.readInt32BE(0);
//减少性能损耗 //减少性能损耗
this.msgIdMap.set(msgId, shortId); this.msgIdMap.set(msgId, shortId);
@@ -110,11 +115,11 @@ class MessageUniqueWrapper {
if (data) { if (data) {
const [msgId, chatTypeStr, peerUid] = data.split('|'); const [msgId, chatTypeStr, peerUid] = data.split('|');
const peer: Peer = { const peer: Peer = {
chatType: parseInt(chatTypeStr), chatType: parseInt(chatTypeStr ?? '0'),
peerUid, peerUid: peerUid ?? '',
guildId: '', guildId: '',
}; };
return { MsgId: msgId, Peer: peer }; return { MsgId: msgId ?? '0', Peer: peer };
} }
return undefined; return undefined;
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { LogWrapper } from '@/common/log'; import { LogWrapper } from '@/common/log';
export function proxyHandlerOf(logger: LogWrapper) { export function proxyHandlerOf(logger: LogWrapper) {
@@ -5,6 +6,7 @@ export function proxyHandlerOf(logger: LogWrapper) {
get(target: any, prop: any, receiver: any) { get(target: any, prop: any, receiver: any) {
if (typeof target[prop] === 'undefined') { if (typeof target[prop] === 'undefined') {
// 如果方法不存在返回一个函数这个函数调用existentMethod // 如果方法不存在返回一个函数这个函数调用existentMethod
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return (..._args: unknown[]) => { return (..._args: unknown[]) => {
logger.logDebug(`${target.constructor.name} has no method ${prop}`); logger.logDebug(`${target.constructor.name} has no method ${prop}`);
}; };

View File

@@ -4,6 +4,7 @@ import { getDefaultQQVersionConfigInfo, getQQPackageInfoPath, getQQVersionConfig
import AppidTable from '@/core/external/appid.json'; import AppidTable from '@/core/external/appid.json';
import { LogWrapper } from '@/common/log'; import { LogWrapper } from '@/common/log';
import { getMajorPath } from '@/core'; import { getMajorPath } from '@/core';
import { QQAppidTableType, QQPackageInfoType, QQVersionConfigType } from './types';
export class QQBasicInfoWrapper { export class QQBasicInfoWrapper {
QQMainPath: string | undefined; QQMainPath: string | undefined;
@@ -86,14 +87,14 @@ export class QQBasicInfoWrapper {
try { try {
const majorAppid = this.getAppidV2ByMajor(fullVersion); const majorAppid = this.getAppidV2ByMajor(fullVersion);
if (majorAppid) { if (majorAppid) {
this.context.logger.log(`[QQ版本兼容性检测] 当前版本Appid未内置 通过Major获取 为了更好的性能请尝试更新NapCat`); this.context.logger.log('[QQ版本兼容性检测] 当前版本Appid未内置 通过Major获取 为了更好的性能请尝试更新NapCat');
return { appid: majorAppid, qua: this.getQUAFallback() }; return { appid: majorAppid, qua: this.getQUAFallback() };
} }
} catch (error) { } catch {
this.context.logger.log(`[QQ版本兼容性检测] 通过Major 获取Appid异常 请检测NapCat/QQNT是否正常`); 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} 版本兼容性不佳,可能会导致一些功能无法正常使用`,); this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,);
return { appid: this.getAppIdFallback(), qua: this.getQUAFallback() }; return { appid: this.getAppIdFallback(), qua: this.getQUAFallback() };
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import https from 'node:https'; import https from 'node:https';
import http from 'node:http'; import http from 'node:http';
@@ -41,11 +42,13 @@ export class RequestUtil {
private static extractCookies(setCookieHeaders: string[], cookies: { [key: string]: string }) { private static extractCookies(setCookieHeaders: string[], cookies: { [key: string]: string }) {
setCookieHeaders.forEach((cookie) => { setCookieHeaders.forEach((cookie) => {
const parts = cookie.split(';')[0].split('='); const parts = cookie.split(';')[0]?.split('=');
const key = parts[0]; if (parts) {
const value = parts[1]; const key = parts[0];
if (key && value && key.length > 0 && value.length > 0) { const value = parts[1];
cookies[key] = value; if (key && value && key.length > 0 && value.length > 0) {
cookies[key] = value;
}
} }
}); });
} }

View File

@@ -54,10 +54,10 @@ class Store {
// 分批次扫描 // 分批次扫描
while (scanned < this.scanLimit && this.scanCursor < keys.length) { while (scanned < this.scanLimit && this.scanCursor < keys.length) {
const key = keys[this.scanCursor++]; const key = keys[this.scanCursor++];
const entry = this.store.get(key)!; const entry = this.store.get(key!)!;
if (entry.expiresAt && entry.expiresAt < now) { if (entry.expiresAt && entry.expiresAt < now) {
this.store.delete(key); this.store.delete(key!);
} }
scanned++; scanned++;

View File

@@ -6,7 +6,7 @@ let osName: string;
try { try {
osName = os.hostname(); osName = os.hostname();
} catch (e) { } catch {
osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4); osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4);
} }

View File

@@ -1,17 +1,17 @@
//QQVersionType //QQVersionType
type QQPackageInfoType = { export type QQPackageInfoType = {
version: string; version: string;
buildVersion: string; buildVersion: string;
platform: string; platform: string;
eleArch: string; eleArch: string;
} }
type QQVersionConfigType = { export type QQVersionConfigType = {
baseVersion: string; baseVersion: string;
curVersion: string; curVersion: string;
prevVersion: string; prevVersion: string;
onErrorVersions: Array<any>; onErrorVersions: Array<unknown>;
buildId: string; buildId: string;
} }
type QQAppidTableType = { export type QQAppidTableType = {
[key: string]: { appid: string, qua: string }; [key: string]: { appid: string, qua: string };
} }

View File

@@ -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 { 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) {
} }
} }

View File

@@ -1,10 +1,11 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
export class NodeIDispatcherAdapter { export class NodeIDispatcherAdapter {
dispatchRequest(arg: unknown) { dispatchRequest(_arg: unknown) {
} }
dispatchCall(arg: unknown) { dispatchCall(_arg: unknown) {
} }
dispatchCallWithJson(arg: unknown) { dispatchCallWithJson(_arg: unknown) {
} }
} }

View File

@@ -1,25 +1,26 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
export class NodeIGlobalAdapter { 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[]) {
} }
} }

View File

@@ -27,6 +27,7 @@ import { encodeSilk } from '@/common/audio';
import { SendMessageContext } from '@/onebot/api'; import { SendMessageContext } from '@/onebot/api';
import { getFileTypeForSendType } from '../helper/msg'; import { getFileTypeForSendType } from '../helper/msg';
import { FFmpegService } from '@/common/ffmpeg'; import { FFmpegService } from '@/common/ffmpeg';
import { rkeyDataType } from '../types/file';
export class NTQQFileApi { export class NTQQFileApi {
context: InstanceContext; context: InstanceContext;
@@ -40,7 +41,7 @@ export class NTQQFileApi {
this.rkeyManager = new RkeyManager([ this.rkeyManager = new RkeyManager([
'https://rkey.napneko.icu/rkeys' '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) { async uploadFile(filePath: string, elementType: ElementType = ElementType.PIC, elementSubType: number = 0) {
const fileMd5 = await calculateFileMD5(filePath); 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}` : ''; const ext = extOrEmpty ? `.${extOrEmpty}` : '';
let fileName = `${path.basename(filePath)}`; let fileName = `${path.basename(filePath)}`;
if (fileName.indexOf('.') === -1) { 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 = { let videoInfo = {
width: 1920, width: 1920,
height: 1080, height: 1080,
@@ -170,10 +171,16 @@ export class NTQQFileApi {
const thumbPath = pathLib.join(pathLib.dirname(thumbDir), `${md5}_0.png`); const thumbPath = pathLib.join(pathLib.dirname(thumbDir), `${md5}_0.png`);
try { try {
videoInfo = await FFmpegService.getVideoInfo(filePath, thumbPath); videoInfo = await FFmpegService.getVideoInfo(filePath, thumbPath);
} catch (error) { } catch {
fs.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64')); 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 thumbSize = (await fsPromises.stat(thumbPath)).size;
const thumbMd5 = await calculateFileMD5(thumbPath); const thumbMd5 = await calculateFileMD5(thumbPath);
context.deleteAfterSentFiles.push(path); context.deleteAfterSentFiles.push(path);
@@ -274,18 +281,18 @@ export class NTQQFileApi {
element.elementType === ElementType.FILE element.elementType === ElementType.FILE
) { ) {
switch (element.elementType) { switch (element.elementType) {
case ElementType.PIC: case ElementType.PIC:
element.picElement!.sourcePath = elementResults[elementIndex]; element.picElement!.sourcePath = elementResults?.[elementIndex] ?? '';
break; break;
case ElementType.VIDEO: case ElementType.VIDEO:
element.videoElement!.filePath = elementResults[elementIndex]; element.videoElement!.filePath = elementResults?.[elementIndex] ?? '';
break; break;
case ElementType.PTT: case ElementType.PTT:
element.pttElement!.filePath = elementResults[elementIndex]; element.pttElement!.filePath = elementResults?.[elementIndex] ?? '';
break; break;
case ElementType.FILE: case ElementType.FILE:
element.fileElement!.filePath = elementResults[elementIndex]; element.fileElement!.filePath = elementResults?.[elementIndex] ?? '';
break; break;
} }
elementIndex++; elementIndex++;
} }
@@ -299,7 +306,7 @@ export class NTQQFileApi {
if (force) { if (force) {
try { try {
await fsPromises.unlink(sourcePath); await fsPromises.unlink(sourcePath);
} catch (e) { } catch {
// //
} }
} else { } else {
@@ -401,27 +408,27 @@ export class NTQQFileApi {
} }
private async getRkeyData() { private async getRkeyData() {
const rkeyData = { const rkeyData: rkeyDataType = {
private_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qEc3Rbib9LP4', private_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qEc3Rbib9LP4',
group_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qffcqm614gds', group_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qffcqm614gds',
online_rkey: false online_rkey: false
}; };
try { 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_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; 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) { if (rkey_expired_private || rkey_expired_group) {
this.packetRkey = await this.core.apis.PacketApi.pkt.operation.FetchRkey(); this.packetRkey = await this.core.apis.PacketApi.pkt.operation.FetchRkey();
} }
if (this.packetRkey && this.packetRkey.length > 0) { if (this.packetRkey && this.packetRkey.length > 0) {
rkeyData.group_rkey = this.packetRkey[1].rkey.slice(6); rkeyData.group_rkey = this.packetRkey[1]?.rkey.slice(6) ?? '';
rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6); rkeyData.private_rkey = this.packetRkey[0]?.rkey.slice(6) ?? '';
rkeyData.online_rkey = true; rkeyData.online_rkey = true;
} }
} }
} catch (error: any) { } catch (error: unknown) {
this.context.logger.logError('获取rkey失败', error.message); this.context.logger.logError('获取rkey失败', (error as Error).message);
} }
if (!rkeyData.online_rkey) { if (!rkeyData.online_rkey) {
@@ -438,7 +445,7 @@ export class NTQQFileApi {
return rkeyData; 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; const rkey = appid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
if (rkeyData.online_rkey) { if (rkeyData.online_rkey) {
return IMAGE_HTTP_HOST_NT + `/download?appid=${appid}&fileid=${imageFileId}&rkey=${rkey}`; return IMAGE_HTTP_HOST_NT + `/download?appid=${appid}&fileid=${imageFileId}&rkey=${rkey}`;

View File

@@ -13,7 +13,7 @@ export class NTQQFriendApi {
async setBuddyRemark(uid: string, remark: string) { async setBuddyRemark(uid: string, remark: string) {
return this.context.session.getBuddyService().setBuddyRemark({ uid, remark }); return this.context.session.getBuddyService().setBuddyRemark({ uid, remark });
} }
async getBuddyV2SimpleInfoMap(refresh = false) { async getBuddyV2SimpleInfoMap() {
const buddyService = this.context.session.getBuddyService(); const buddyService = this.context.session.getBuddyService();
const buddyListV2 = await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL); const buddyListV2 = await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
const uids = buddyListV2.data.flatMap(item => item.buddyUids); const uids = buddyListV2.data.flatMap(item => item.buddyUids);
@@ -24,13 +24,13 @@ export class NTQQFriendApi {
); );
} }
async getBuddy(refresh = false): Promise<FriendV2[]> { async getBuddy(): Promise<FriendV2[]> {
return Array.from((await this.getBuddyV2SimpleInfoMap(refresh)).values()); 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 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!)); data.forEach((value) => retMap.set(value.uin!, value.uid!));
return retMap; return retMap;
} }

View File

@@ -59,7 +59,7 @@ export class NTQQGroupApi {
}, pskey); }, pskey);
} }
async getGroupShutUpMemberList(groupCode: string) { async getGroupShutUpMemberList(groupCode: string): Promise<ShutUpGroupMember[]> {
const executor: TaskExecutor<ShutUpGroupMember[]> = async (resolve, reject, onCancel) => { const executor: TaskExecutor<ShutUpGroupMember[]> = async (resolve, reject, onCancel) => {
this.core.eventWrapper.registerListen( this.core.eventWrapper.registerListen(
'NodeIKernelGroupListener/onShutUpMemberListChanged', 'NodeIKernelGroupListener/onShutUpMemberListChanged',
@@ -215,6 +215,9 @@ export class NTQQGroupApi {
guildId: '', guildId: '',
peerUid: groupCode, peerUid: groupCode,
}, msgId, 1, false); }, msgId, 1, false);
if (!MsgData.msgList[0]) {
throw new Error('消息不存在');
}
const param = { const param = {
groupCode: groupCode, groupCode: groupCode,
msgRandom: parseInt(MsgData.msgList[0].msgRandom), msgRandom: parseInt(MsgData.msgList[0].msgRandom),
@@ -255,6 +258,9 @@ export class NTQQGroupApi {
guildId: '', guildId: '',
peerUid: groupCode, peerUid: groupCode,
}, msgId, 1, false); }, msgId, 1, false);
if (!MsgData.msgList[0]) {
throw new Error('消息不存在');
}
const param = { const param = {
groupCode: groupCode, groupCode: groupCode,
msgRandom: parseInt(MsgData.msgList[0].msgRandom), msgRandom: parseInt(MsgData.msgList[0].msgRandom),

View File

@@ -4,4 +4,6 @@ export * from './group';
export * from './msg'; export * from './msg';
export * from './user'; export * from './user';
export * from './webapi'; export * from './webapi';
export * from './system'; export * from './system';
export * from './packet';
export * from './file';

View File

@@ -201,7 +201,7 @@ export class NTQQMsgApi {
return this.context.session.getMsgService().getTempChatInfo(chatType, peerUid); 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 !== '') { if (peer.chatType === ChatType.KCHATTYPETEMPC2CFROMGROUP && peer.guildId && peer.guildId !== '') {
const member = await this.core.apis.GroupApi.getGroupMember(peer.guildId, peer.peerUid); const member = await this.core.apis.GroupApi.getGroupMember(peer.guildId, peer.peerUid);
@@ -268,7 +268,7 @@ export class NTQQMsgApi {
if (!arkElement) { if (!arkElement) {
continue; continue;
} }
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData ?? ''); const forwardData: { app: string } = JSON.parse(arkElement.arkElement?.bytesData ?? '');
if (forwardData.app != 'com.tencent.multimsg') { if (forwardData.app != 'com.tencent.multimsg') {
continue; continue;
} }

View File

@@ -1,9 +1,9 @@
import * as os from 'os'; import * as os from 'os';
import offset from '@/core/external/offset.json'; import offset from '@/core/external/offset.json';
import { InstanceContext, NapCatCore } from "@/core"; import { InstanceContext, NapCatCore } from '@/core';
import { LogWrapper } from "@/common/log"; import { LogWrapper } from '@/common/log';
import { PacketClientSession } from "@/core/packet/clientSession"; import { PacketClientSession } from '@/core/packet/clientSession';
import { napCatVersion } from "@/common/version"; import { napCatVersion } from '@/common/version';
interface OffsetType { interface OffsetType {
[key: string]: { [key: string]: {

View File

@@ -25,7 +25,7 @@ export class NTQQSystemApi {
this.context.session.getMsgService().getOnLineDev(); this.context.session.getMsgService().getOnLineDev();
} }
async getArkJsonCollection(cid: string) { async getArkJsonCollection() {
return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelCollectionService/collectionArkShare', '1717662698058'); return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelCollectionService/collectionArkShare', '1717662698058');
} }

View File

@@ -69,7 +69,7 @@ export class NTQQUserApi {
} }
async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) { 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', 'NodeIKernelProfileService/fetchUserDetailInfo',
'NodeIKernelProfileListener/onUserDetailInfoChanged', 'NodeIKernelProfileListener/onUserDetailInfoChanged',
[ [
@@ -130,10 +130,10 @@ export class NTQQUserApi {
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + 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'; '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
const data = await RequestUtil.HttpsGetCookies(requestUrl); 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 { try {
const pskey = (await this.getPSkey([domain])).domainPskeyMap.get(domain); const pskey = (await this.getPSkey([domain])).domainPskeyMap.get(domain);
if (pskey) data.p_skey = pskey; if (pskey) data['p_skey'] = pskey;
} catch { } catch {
return data; return data;
} }
@@ -145,7 +145,7 @@ export class NTQQUserApi {
return await this.context.session.getTipOffService().getPskey(domainList, true); 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({ const robotUinRanges = await this.context.session.getRobotService().getRobotUinRange({
justFetchMsgConfig: '1', justFetchMsgConfig: '1',
type: 1, type: 1,

View File

@@ -32,7 +32,7 @@ export class NTQQWebApi {
}).toString()}`; }).toString()}`;
try { try {
return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
} catch (e) { } catch {
return undefined; 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); //logDebug('webapi 获取群成员', GroupCode);
const memberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>(); const memberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>();
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com'); const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
@@ -88,7 +88,9 @@ export class NTQQWebApi {
return []; return [];
} else { } else {
for (const key in fastRet.mems) { for (const key in fastRet.mems) {
memberData.push(fastRet.mems[key]); if (fastRet.mems[key]) {
memberData.push(fastRet.mems[key]);
}
} }
} }
//初始化获取PageNum //初始化获取PageNum
@@ -116,7 +118,9 @@ export class NTQQWebApi {
continue; continue;
} }
for (const key in ret.mems) { for (const key in ret.mems) {
memberData.push(ret.mems[key]); if (ret.mems[key]) {
memberData.push(ret.mems[key]);
}
} }
} }
return memberData; return memberData;
@@ -185,7 +189,7 @@ export class NTQQWebApi {
{ 'Cookie': this.cookieToString(cookieObject) } { 'Cookie': this.cookieToString(cookieObject) }
); );
return ret; return ret;
} catch (e) { } catch {
return undefined; return undefined;
} }
} }
@@ -210,12 +214,12 @@ export class NTQQWebApi {
{ 'Cookie': this.cookieToString(cookieObject) } { 'Cookie': this.cookieToString(cookieObject) }
); );
return ret?.ec === 0 ? ret : undefined; return ret?.ec === 0 ? ret : undefined;
} catch (e) { } catch {
return undefined; return undefined;
} }
} }
private async getDataInternal(cookieObject: any, groupCode: string, type: number) { private async getDataInternal(cookieObject: { [key: string]: string }, groupCode: string, type: number) {
let resJson; let resJson;
try { try {
const res = await RequestUtil.HttpGetText( const res = await RequestUtil.HttpGetText(
@@ -228,7 +232,7 @@ export class NTQQWebApi {
{ 'Cookie': this.cookieToString(cookieObject) } { 'Cookie': this.cookieToString(cookieObject) }
); );
const match = /window\.__INITIAL_STATE__=(.*?);/.exec(res); const match = /window\.__INITIAL_STATE__=(.*?);/.exec(res);
if (match) { if (match?.[1]) {
resJson = JSON.parse(match[1].trim()); resJson = JSON.parse(match[1].trim());
} }
return type === 1 ? resJson?.talkativeList : resJson?.actorList; 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); const data = await this.getDataInternal(cookieObject, groupCode, type);
if (!data) { if (!data) {
this.context.logger.logError(`获取类型 ${type} 的荣誉信息失败`); this.context.logger.logError(`获取类型 ${type} 的荣誉信息失败`);
return []; return [];
} }
return data.map((item: any) => ({ return data.map((item: {
uin: string,
name: string,
avatar: string,
desc: string,
}) => ({
user_id: item?.uin, user_id: item?.uin,
nickname: item?.name, nickname: item?.name,
avatar: item?.avatar, avatar: item?.avatar,
@@ -254,7 +263,15 @@ export class NTQQWebApi {
async getGroupHonorInfo(groupCode: string, getType: WebHonorType) { async getGroupHonorInfo(groupCode: string, getType: WebHonorType) {
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com'); 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) { if (getType === WebHonorType.TALKATIVE || getType === WebHonorType.ALL) {
const talkativeList = await this.getHonorList(cookieObject, groupCode, 1); const talkativeList = await this.getHonorList(cookieObject, groupCode, 1);
@@ -284,12 +301,12 @@ export class NTQQWebApi {
return HonorInfo; return HonorInfo;
} }
private cookieToString(cookieObject: any) { private cookieToString(cookieObject: { [key: string]: string }) {
return Object.entries(cookieObject).map(([key, value]) => `${key}=${value}`).join('; '); return Object.entries(cookieObject).map(([key, value]) => `${key}=${value}`).join('; ');
} }
public getBknFromCookie(cookieObject: any) { public getBknFromCookie(cookieObject: { [key: string]: string }) {
const sKey = cookieObject.skey as string; const sKey = cookieObject['skey'] as string;
let hash = 5381; let hash = 5381;
for (let i = 0; i < sKey.length; i++) { for (let i = 0; i < sKey.length; i++) {
@@ -322,18 +339,18 @@ export class NTQQWebApi {
data: pskey, data: pskey,
appid: 5 appid: 5
}, },
appid: "qun", appid: 'qun',
checksum: img_md5, checksum: img_md5,
check_type: 0, check_type: 0,
file_len: img_size, file_len: img_size,
env: { env: {
refer: "qzone", refer: 'qzone',
deviceInfo: "h5" deviceInfo: 'h5'
}, },
model: 0, model: 0,
biz_req: { biz_req: {
sPicTitle: img_name, sPicTitle: img_name,
sPicDesc: "", sPicDesc: '',
sAlbumName: sAlbumName, sAlbumName: sAlbumName,
sAlbumID: sAlbumID, sAlbumID: sAlbumID,
iAlbumTypeID: 0, iAlbumTypeID: 0,
@@ -341,7 +358,7 @@ export class NTQQWebApi {
iUploadType: 0, iUploadType: 0,
iUpPicType: 0, iUpPicType: 0,
iBatchID: time, iBatchID: time,
sPicPath: "", sPicPath: '',
iPicWidth: 0, iPicWidth: 0,
iPicHight: 0, iPicHight: 0,
iWaterType: 0, iWaterType: 0,
@@ -349,19 +366,19 @@ export class NTQQWebApi {
iNeedFeeds: 1, iNeedFeeds: 1,
iUploadTime: time, iUploadTime: time,
mapExt: { mapExt: {
appid: "qun", appid: 'qun',
userid: gc userid: gc
} }
}, },
session: "", session: '',
asy_upload: 0, asy_upload: 0,
cmd: "FileUpload" cmd: 'FileUpload'
}] }]
}; };
const api = `https://h5.qzone.qq.com/webapp/json/sliceUpload/FileBatchControl/${img_md5}?g_tk=${GTK}`; const api = `https://h5.qzone.qq.com/webapp/json/sliceUpload/FileBatchControl/${img_md5}?g_tk=${GTK}`;
const post = await RequestUtil.HttpGetJson(api, 'POST', body, { const post = await RequestUtil.HttpGetJson(api, 'POST', body, {
"Cookie": cookie, 'Cookie': cookie,
"Content-Type": "application/json" 'Content-Type': 'application/json'
}); });
return post; return post;

View File

@@ -1,5 +1,5 @@
// TODO: further refactor in NapCat.Packet v2 // 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 = { const LikeDetail = {
txt: ProtoField(1, ScalarType.STRING), txt: ProtoField(1, ScalarType.STRING),

View File

@@ -32,7 +32,7 @@ export class RkeyManager {
} }
if (this.failureCount >= this.FAILURE_LIMIT) { if (this.failureCount >= this.FAILURE_LIMIT) {
this.logger.logError(`[Rkey] 服务存在异常, 图片使用FallBack机制`); this.logger.logError('[Rkey] 服务存在异常, 图片使用FallBack机制');
throw new Error('获取rkey失败次数过多请稍后再试'); throw new Error('获取rkey失败次数过多请稍后再试');
} }
@@ -51,7 +51,7 @@ export class RkeyManager {
return now > this.rkeyData.expired_time; return now > this.rkeyData.expired_time;
} }
async refreshRkey(): Promise<any> { async refreshRkey() {
//刷新rkey //刷新rkey
for (const url of this.serverUrl) { for (const url of this.serverUrl) {
try { try {

View File

@@ -1,5 +1,5 @@
import os from "node:os"; import os from 'node:os';
import EventEmitter from "node:events"; import EventEmitter from 'node:events';
export interface SystemStatus { export interface SystemStatus {
cpu: { cpu: {
@@ -35,9 +35,9 @@ export class StatusHelper {
const { total, active } = currentTimes.map((times, index) => { const { total, active } = currentTimes.map((times, index) => {
const prevTimes = this.cpuTimes[index]; const prevTimes = this.cpuTimes[index];
const totalCurrent = times.user + times.nice + times.sys + times.idle + times.irq; 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 activeCurrent = totalCurrent - times.idle;
const activePrev = totalPrev - prevTimes.idle; const activePrev = totalPrev - (prevTimes?.idle ?? 0);
return { return {
total: totalCurrent - totalPrev, total: totalCurrent - totalPrev,
active: activeCurrent - activePrev active: activeCurrent - activePrev
@@ -49,8 +49,8 @@ export class StatusHelper {
this.cpuTimes = currentTimes; this.cpuTimes = currentTimes;
return { return {
usage: this.replaceNaN(((active / total) * 100)).toFixed(2), usage: this.replaceNaN(((active / total) * 100)).toFixed(2),
model: os.cpus()[0].model, model: os.cpus()[0]?.model ?? 'none',
speed: os.cpus()[0].speed, speed: os.cpus()[0]?.speed ?? 0,
core: os.cpus().length core: os.cpus().length
}; };
} }

View File

@@ -24,7 +24,7 @@ import path from 'node:path';
import fs from 'node:fs'; import fs from 'node:fs';
import { hostname, systemName, systemVersion } from '@/common/system'; import { hostname, systemName, systemVersion } from '@/common/system';
import { NTEventWrapper } from '@/common/event'; 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 { NapCatConfigLoader } from '@/core/helper/config';
import os from 'node:os'; import os from 'node:os';
import { NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners'; import { NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners';
@@ -52,13 +52,13 @@ export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
} }
let wrapperNodePath = path.resolve(appPath, 'wrapper.node'); let wrapperNodePath = path.resolve(appPath, 'wrapper.node');
if (!fs.existsSync(wrapperNodePath)) { if (!fs.existsSync(wrapperNodePath)) {
wrapperNodePath = path.join(appPath, `./resources/app/wrapper.node`); wrapperNodePath = path.join(appPath, './resources/app/wrapper.node');
} }
//老版本兼容 未来去掉 //老版本兼容 未来去掉
if (!fs.existsSync(wrapperNodePath)) { if (!fs.existsSync(wrapperNodePath)) {
wrapperNodePath = path.join(path.dirname(process.execPath), `./resources/app/versions/${QQVersion}/wrapper.node`); 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); process.dlopen(nativemodule, wrapperNodePath);
return nativemodule.exports; return nativemodule.exports;
} }
@@ -74,7 +74,7 @@ export function getMajorPath(QQVersion: string): string {
} }
let majorPath = path.resolve(appPath, 'major.node'); let majorPath = path.resolve(appPath, 'major.node');
if (!fs.existsSync(majorPath)) { if (!fs.existsSync(majorPath)) {
majorPath = path.join(appPath, `./resources/app/major.node`); majorPath = path.join(appPath, './resources/app/major.node');
} }
//老版本兼容 未来去掉 //老版本兼容 未来去掉
if (!fs.existsSync(majorPath)) { if (!fs.existsSync(majorPath)) {
@@ -177,7 +177,7 @@ export class NapCatCore {
profileListener.onSelfStatusChanged = (Info: SelfStatusInfo) => { profileListener.onSelfStatusChanged = (Info: SelfStatusInfo) => {
if (Info.status == 20) { if (Info.status == 20) {
this.selfInfo.online = false; this.selfInfo.online = false;
this.context.logger.log("账号状态变更为离线"); this.context.logger.log('账号状态变更为离线');
} else { } else {
this.selfInfo.online = true; this.selfInfo.online = true;
} }

View File

@@ -1,9 +1,9 @@
import { LRUCache } from "@/common/lru-cache"; import { LRUCache } from '@/common/lru-cache';
import crypto, { createHash } from "crypto"; import crypto, { createHash } from 'crypto';
import { OidbPacket, PacketHexStr } from "@/core/packet/transformer/base"; import { OidbPacket, PacketHexStr } from '@/core/packet/transformer/base';
import { LogStack } from "@/core/packet/context/clientContext"; import { LogStack } from '@/core/packet/context/clientContext';
import { NapCoreContext } from "@/core/packet/context/napCoreContext"; import { NapCoreContext } from '@/core/packet/context/napCoreContext';
import { PacketLogger } from "@/core/packet/context/loggerContext"; import { PacketLogger } from '@/core/packet/context/loggerContext';
export interface RecvPacket { export interface RecvPacket {
type: string, // 仅recv type: string, // 仅recv

View File

@@ -1,13 +1,13 @@
import { createHash } from "crypto"; import { createHash } from 'crypto';
import path, { dirname } from "path"; import path, { dirname } from 'path';
import { fileURLToPath } from "url"; import { fileURLToPath } from 'url';
import fs from "fs"; import fs from 'fs';
import { IPacketClient } from "@/core/packet/client/baseClient"; import { IPacketClient } from '@/core/packet/client/baseClient';
import { constants } from "node:os"; import { constants } from 'node:os';
import { LRUCache } from "@/common/lru-cache"; import { LRUCache } from '@/common/lru-cache';
import { LogStack } from "@/core/packet/context/clientContext"; import { LogStack } from '@/core/packet/context/clientContext';
import { NapCoreContext } from "@/core/packet/context/napCoreContext"; import { NapCoreContext } from '@/core/packet/context/napCoreContext';
import { PacketLogger } from "@/core/packet/context/loggerContext"; import { PacketLogger } from '@/core/packet/context/loggerContext';
// 0 send 1 recv // 0 send 1 recv
export interface NativePacketExportType { export interface NativePacketExportType {

View File

@@ -1,8 +1,8 @@
import { Data, WebSocket, ErrorEvent } from "ws"; import { Data, WebSocket, ErrorEvent } from 'ws';
import { IPacketClient, RecvPacket } from "@/core/packet/client/baseClient"; import { IPacketClient, RecvPacket } from '@/core/packet/client/baseClient';
import { LogStack } from "@/core/packet/context/clientContext"; import { LogStack } from '@/core/packet/context/clientContext';
import { NapCoreContext } from "@/core/packet/context/napCoreContext"; import { NapCoreContext } from '@/core/packet/context/napCoreContext';
import { PacketLogger } from "@/core/packet/context/loggerContext"; import { PacketLogger } from '@/core/packet/context/loggerContext';
export class WsPacketClient extends IPacketClient { export class WsPacketClient extends IPacketClient {
private websocket: WebSocket | null = null; private websocket: WebSocket | null = null;
@@ -23,7 +23,7 @@ export class WsPacketClient extends IPacketClient {
check(): boolean { check(): boolean {
if (!this.napcore.config.packetServer) { if (!this.napcore.config.packetServer) {
this.logStack.pushLogWarn(`wsPacketClient 未配置服务器地址`); this.logStack.pushLogWarn('wsPacketClient 未配置服务器地址');
return false; return false;
} }
return true; return true;
@@ -52,7 +52,7 @@ export class WsPacketClient extends IPacketClient {
try { try {
await this.connect(); await this.connect();
return; return;
} catch (error) { } catch {
this.reconnectAttempts++; this.reconnectAttempts++;
this.logStack.pushLogWarn(`${this.reconnectAttempts}/${this.maxReconnectAttempts} 次尝试重连失败!`); this.logStack.pushLogWarn(`${this.reconnectAttempts}/${this.maxReconnectAttempts} 次尝试重连失败!`);
await this.delay(5000); await this.delay(5000);
@@ -80,7 +80,7 @@ export class WsPacketClient extends IPacketClient {
}; };
this.websocket.onclose = () => { this.websocket.onclose = () => {
this.available = false; this.available = false;
this.logger.warn(`WebSocket 连接关闭,尝试重连...`); this.logger.warn('WebSocket 连接关闭,尝试重连...');
reject(new Error('WebSocket 连接关闭')); reject(new Error('WebSocket 连接关闭'));
}; };
this.websocket.onmessage = (event) => this.handleMessage(event.data).catch(err => { this.websocket.onmessage = (event) => this.handleMessage(event.data).catch(err => {

View File

@@ -1,5 +1,5 @@
import { PacketContext } from "@/core/packet/context/packetContext"; import { PacketContext } from '@/core/packet/context/packetContext';
import { NapCatCore } from "@/core"; import { NapCatCore } from '@/core';
export class PacketClientSession { export class PacketClientSession {
private readonly context: PacketContext; private readonly context: PacketContext;

View File

@@ -1,15 +1,15 @@
import { IPacketClient } from "@/core/packet/client/baseClient"; import { IPacketClient } from '@/core/packet/client/baseClient';
import { NativePacketClient } from "@/core/packet/client/nativeClient"; import { NativePacketClient } from '@/core/packet/client/nativeClient';
import { WsPacketClient } from "@/core/packet/client/wsClient"; import { WsPacketClient } from '@/core/packet/client/wsClient';
import { OidbPacket } from "@/core/packet/transformer/base"; import { OidbPacket } from '@/core/packet/transformer/base';
import { PacketLogger } from "@/core/packet/context/loggerContext"; import { PacketLogger } from '@/core/packet/context/loggerContext';
import { NapCoreContext } from "@/core/packet/context/napCoreContext"; import { NapCoreContext } from '@/core/packet/context/napCoreContext';
type clientPriority = { type clientPriorityType = {
[key: number]: (napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) => IPacketClient; [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), 10: (napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) => new NativePacketClient(napCore, logger, logStack),
1: (napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) => new WsPacketClient(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> { async sendOidbPacket<T extends boolean = false>(pkt: OidbPacket, rsp?: T): Promise<T extends true ? Buffer : void> {
const raw = await this._client.sendOidbPacket(pkt, rsp); 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 { private newClient(): IPacketClient {
const prefer = this.napCore.config.packetBackend; const prefer = this.napCore.config.packetBackend;
let client: IPacketClient | null; let client: IPacketClient | null;
switch (prefer) { switch (prefer) {
case "native": case 'native':
this.logger.info("使用指定的 NativePacketClient 作为后端"); this.logger.info('使用指定的 NativePacketClient 作为后端');
client = new NativePacketClient(this.napCore, this.logger, this.logStack); client = new NativePacketClient(this.napCore, this.logger, this.logStack);
break; break;
case "frida": case 'frida':
this.logger.info("[Core] [Packet] 使用指定的 FridaPacketClient 作为后端"); this.logger.info('[Core] [Packet] 使用指定的 FridaPacketClient 作为后端');
client = new WsPacketClient(this.napCore, this.logger, this.logStack); client = new WsPacketClient(this.napCore, this.logger, this.logStack);
break; break;
case "auto": case 'auto':
case undefined: case undefined:
client = this.judgeClient(); client = this.judgeClient();
break; break;
@@ -101,10 +101,10 @@ export class PacketClientContext {
client = null; client = null;
} }
if (!client?.check()) { if (!client?.check()) {
throw new Error("[Core] [Packet] 无可用的后端NapCat.Packet将不会加载"); throw new Error('[Core] [Packet] 无可用的后端NapCat.Packet将不会加载');
} }
if (!client) { if (!client) {
throw new Error("[Core] [Packet] 后端异常NapCat.Packet将不会加载"); throw new Error('[Core] [Packet] 后端异常NapCat.Packet将不会加载');
} }
return client; return client;
} }
@@ -120,7 +120,7 @@ export class PacketClientContext {
.sort((a, b) => b.score - a.score); .sort((a, b) => b.score - a.score);
const selectedClient = sortedClients[0]?.client; const selectedClient = sortedClients[0]?.client;
if (!selectedClient) { if (!selectedClient) {
throw new Error("[Core] [Packet] 无可用的后端NapCat.Packet将不会加载"); throw new Error('[Core] [Packet] 无可用的后端NapCat.Packet将不会加载');
} }
this.logger.info(`自动选择 ${selectedClient.constructor.name} 作为后端`); this.logger.info(`自动选择 ${selectedClient.constructor.name} 作为后端`);
return selectedClient; return selectedClient;

View File

@@ -1,5 +1,6 @@
import { LogLevel, LogWrapper } from "@/common/log"; /* eslint-disable @typescript-eslint/no-explicit-any */
import { NapCoreContext } from "@/core/packet/context/napCoreContext"; import { LogLevel, LogWrapper } from '@/common/log';
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
// TODO: check bind? // TODO: check bind?
export class PacketLogger { export class PacketLogger {
@@ -10,7 +11,7 @@ export class PacketLogger {
} }
private _log(level: LogLevel, ...msg: any[]): void { 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 { debug(...msg: any[]): void {

View File

@@ -1,4 +1,4 @@
import { NapCatCore } from "@/core"; import { NapCatCore } from '@/core';
export interface NapCoreCompatBasicInfo { export interface NapCoreCompatBasicInfo {
readonly uin: number; readonly uin: number;

View File

@@ -1,20 +1,20 @@
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import { PacketContext } from "@/core/packet/context/packetContext"; import { PacketContext } from '@/core/packet/context/packetContext';
import * as trans from "@/core/packet/transformer"; import * as trans from '@/core/packet/transformer';
import { PacketMsg } from "@/core/packet/message/message"; import { PacketMsg } from '@/core/packet/message/message';
import { import {
PacketMsgFileElement, PacketMsgFileElement,
PacketMsgPicElement, PacketMsgPicElement,
PacketMsgPttElement, PacketMsgPttElement,
PacketMsgVideoElement PacketMsgVideoElement
} from "@/core/packet/message/element"; } from '@/core/packet/message/element';
import { ChatType } from "@/core"; import { ChatType } from '@/core';
import { MiniAppRawData, MiniAppReqParams } from "@/core/packet/entities/miniApp"; import { MiniAppRawData, MiniAppReqParams } from '@/core/packet/entities/miniApp';
import { AIVoiceChatType } from "@/core/packet/entities/aiChat"; import { AIVoiceChatType } from '@/core/packet/entities/aiChat';
import { NapProtoDecodeStructType, NapProtoEncodeStructType } from "@napneko/nap-proto-core"; import { NapProtoDecodeStructType, NapProtoEncodeStructType } from '@napneko/nap-proto-core';
import { IndexNode, MsgInfo } from "@/core/packet/transformer/proto"; import { IndexNode, MsgInfo } from '@/core/packet/transformer/proto';
import { OidbPacket } from "@/core/packet/transformer/base"; import { OidbPacket } from '@/core/packet/transformer/base';
import { ImageOcrResult } from "@/core/packet/entities/ocrResult"; import { ImageOcrResult } from '@/core/packet/entities/ocrResult';
export class PacketOperationContext { export class PacketOperationContext {
private readonly context: PacketContext; private readonly context: PacketContext;
@@ -61,7 +61,7 @@ export class PacketOperationContext {
} }
status = Number((extBigInt & 0xff00n) + ((extBigInt >> 16n) & 0xffn)); status = Number((extBigInt & 0xff00n) + ((extBigInt >> 16n) & 0xffn));
return { status: 10, ext_status: status }; return { status: 10, ext_status: status };
} catch (e) { } catch {
return undefined; return undefined;
} }
} }

View File

@@ -1,10 +1,10 @@
import { PacketHighwayContext } from "@/core/packet/highway/highwayContext"; import { PacketHighwayContext } from '@/core/packet/highway/highwayContext';
import { NapCatCore } from "@/core"; import { NapCatCore } from '@/core';
import { PacketLogger } from "@/core/packet/context/loggerContext"; import { PacketLogger } from '@/core/packet/context/loggerContext';
import { NapCoreContext } from "@/core/packet/context/napCoreContext"; import { NapCoreContext } from '@/core/packet/context/napCoreContext';
import { PacketClientContext } from "@/core/packet/context/clientContext"; import { PacketClientContext } from '@/core/packet/context/clientContext';
import { PacketOperationContext } from "@/core/packet/context/operationContext"; import { PacketOperationContext } from '@/core/packet/context/operationContext';
import { PacketMsgConverter } from "@/core/packet/message/converter"; import { PacketMsgConverter } from '@/core/packet/message/converter';
export class PacketContext { export class PacketContext {
readonly msgConverter: PacketMsgConverter; readonly msgConverter: PacketMsgConverter;

View File

@@ -1,9 +1,9 @@
import * as stream from 'node:stream'; import * as stream from 'node:stream';
import { ReadStream } from "node:fs"; import { ReadStream } from 'node:fs';
import { HighwayTcpUploader } from "@/core/packet/highway/uploader/highwayTcpUploader"; import { HighwayTcpUploader } from '@/core/packet/highway/uploader/highwayTcpUploader';
import { HighwayHttpUploader } from "@/core/packet/highway/uploader/highwayHttpUploader"; import { HighwayHttpUploader } from '@/core/packet/highway/uploader/highwayHttpUploader';
import { PacketHighwaySig } from "@/core/packet/highway/highwayContext"; import { PacketHighwaySig } from '@/core/packet/highway/highwayContext';
import { PacketLogger } from "@/core/packet/context/loggerContext"; import { PacketLogger } from '@/core/packet/context/loggerContext';
export interface PacketHighwayTrans { export interface PacketHighwayTrans {
uin: string; uin: string;
@@ -27,7 +27,8 @@ export class PacketHighwayClient {
port: number = 80; port: number = 80;
logger: PacketLogger; 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.sig = sig;
this.logger = logger; this.logger = logger;
} }

View File

@@ -1,4 +1,4 @@
import assert from "node:assert"; import assert from 'node:assert';
export class Frame{ export class Frame{
static pack(head: Buffer, body: Buffer): Buffer { static pack(head: Buffer, body: Buffer): Buffer {

View File

@@ -1,22 +1,22 @@
import { PacketHighwayClient } from "@/core/packet/highway/client"; import { PacketHighwayClient } from '@/core/packet/highway/client';
import { PacketLogger } from "@/core/packet/context/loggerContext"; import { PacketLogger } from '@/core/packet/context/loggerContext';
import FetchSessionKey from "@/core/packet/transformer/highway/FetchSessionKey"; import FetchSessionKey from '@/core/packet/transformer/highway/FetchSessionKey';
import { int32ip2str, oidbIpv4s2HighwayIpv4s } from "@/core/packet/highway/utils"; import { int32ip2str, oidbIpv4s2HighwayIpv4s } from '@/core/packet/highway/utils';
import { import {
PacketMsgFileElement, PacketMsgFileElement,
PacketMsgPicElement, PacketMsgPicElement,
PacketMsgPttElement, PacketMsgPttElement,
PacketMsgVideoElement PacketMsgVideoElement
} from "@/core/packet/message/element"; } from '@/core/packet/message/element';
import { ChatType, Peer } from "@/core"; import { ChatType, Peer } from '@/core';
import { calculateSha1, calculateSha1StreamBytes, computeMd5AndLengthWithLimit } from "@/core/packet/utils/crypto/hash"; import { calculateSha1, calculateSha1StreamBytes, computeMd5AndLengthWithLimit } from '@/core/packet/utils/crypto/hash';
import UploadGroupImage from "@/core/packet/transformer/highway/UploadGroupImage"; import UploadGroupImage from '@/core/packet/transformer/highway/UploadGroupImage';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import * as trans from "@/core/packet/transformer"; import * as trans from '@/core/packet/transformer';
import fs from "fs"; import fs from 'fs';
import { NapCoreContext } from "@/core/packet/context/napCoreContext"; import { NapCoreContext } from '@/core/packet/context/napCoreContext';
import { PacketClientContext } from "@/core/packet/context/clientContext"; import { PacketClientContext } from '@/core/packet/context/clientContext';
export const BlockSize = 1024 * 1024; export const BlockSize = 1024 * 1024;
@@ -142,7 +142,7 @@ export class PacketHighwayContext {
const resp = await this.client.sendOidbPacket(req, true); const resp = await this.client.sendOidbPacket(req, true);
const preRespData = UploadGroupImage.parse(resp); const preRespData = UploadGroupImage.parse(resp);
const ukey = preRespData.upload.uKey; const ukey = preRespData.upload.uKey;
if (ukey && ukey != "") { if (ukey && ukey != '') {
this.logger.debug(`[Highway] uploadGroupImageReq get upload ukey: ${ukey}, need upload!`); this.logger.debug(`[Highway] uploadGroupImageReq get upload ukey: ${ukey}, need upload!`);
const index = preRespData.upload.msgInfo.msgInfoBody[0].index; const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
const sha1 = Buffer.from(index.info.fileSha1, 'hex'); const sha1 = Buffer.from(index.info.fileSha1, 'hex');
@@ -179,7 +179,7 @@ export class PacketHighwayContext {
const resp = await this.client.sendOidbPacket(req, true); const resp = await this.client.sendOidbPacket(req, true);
const preRespData = trans.UploadPrivateImage.parse(resp); const preRespData = trans.UploadPrivateImage.parse(resp);
const ukey = preRespData.upload.uKey; const ukey = preRespData.upload.uKey;
if (ukey && ukey != "") { if (ukey && ukey != '') {
this.logger.debug(`[Highway] uploadC2CImageReq get upload ukey: ${ukey}, need upload!`); this.logger.debug(`[Highway] uploadC2CImageReq get upload ukey: ${ukey}, need upload!`);
const index = preRespData.upload.msgInfo.msgInfoBody[0].index; const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
const sha1 = Buffer.from(index.info.fileSha1, 'hex'); const sha1 = Buffer.from(index.info.fileSha1, 'hex');
@@ -210,14 +210,14 @@ export class PacketHighwayContext {
} }
private async uploadGroupVideo(groupUin: number, video: PacketMsgVideoElement): Promise<void> { 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.fileSha1 = Buffer.from(await calculateSha1(video.filePath)).toString('hex');
video.thumbSha1 = Buffer.from(await calculateSha1(video.thumbPath)).toString('hex'); video.thumbSha1 = Buffer.from(await calculateSha1(video.thumbPath)).toString('hex');
const req = trans.UploadGroupVideo.build(groupUin, video); const req = trans.UploadGroupVideo.build(groupUin, video);
const resp = await this.client.sendOidbPacket(req, true); const resp = await this.client.sendOidbPacket(req, true);
const preRespData = trans.UploadGroupVideo.parse(resp); const preRespData = trans.UploadGroupVideo.parse(resp);
const ukey = preRespData.upload.uKey; const ukey = preRespData.upload.uKey;
if (ukey && ukey != "") { if (ukey && ukey != '') {
this.logger.debug(`[Highway] uploadGroupVideoReq get upload video ukey: ${ukey}, need upload!`); this.logger.debug(`[Highway] uploadGroupVideoReq get upload video ukey: ${ukey}, need upload!`);
const index = preRespData.upload.msgInfo.msgInfoBody[0].index; const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
const md5 = Buffer.from(index.info.fileHash, 'hex'); 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!`); this.logger.debug(`[Highway] uploadGroupVideoReq get upload invalid ukey ${ukey}, don't need upload!`);
} }
const subFile = preRespData.upload.subFileInfos[0]; 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!`); this.logger.debug(`[Highway] uploadGroupVideoReq get upload video thumb ukey: ${subFile.uKey}, need upload!`);
const index = preRespData.upload.msgInfo.msgInfoBody[1].index; const index = preRespData.upload.msgInfo.msgInfoBody[1].index;
const md5 = Buffer.from(index.info.fileHash, 'hex'); const md5 = Buffer.from(index.info.fileHash, 'hex');
@@ -275,14 +275,14 @@ export class PacketHighwayContext {
} }
private async uploadC2CVideo(peerUid: string, video: PacketMsgVideoElement): Promise<void> { 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.fileSha1 = Buffer.from(await calculateSha1(video.filePath)).toString('hex');
video.thumbSha1 = Buffer.from(await calculateSha1(video.thumbPath)).toString('hex'); video.thumbSha1 = Buffer.from(await calculateSha1(video.thumbPath)).toString('hex');
const req = trans.UploadPrivateVideo.build(peerUid, video); const req = trans.UploadPrivateVideo.build(peerUid, video);
const resp = await this.client.sendOidbPacket(req, true); const resp = await this.client.sendOidbPacket(req, true);
const preRespData = trans.UploadPrivateVideo.parse(resp); const preRespData = trans.UploadPrivateVideo.parse(resp);
const ukey = preRespData.upload.uKey; const ukey = preRespData.upload.uKey;
if (ukey && ukey != "") { if (ukey && ukey != '') {
this.logger.debug(`[Highway] uploadC2CVideoReq get upload video ukey: ${ukey}, need upload!`); this.logger.debug(`[Highway] uploadC2CVideoReq get upload video ukey: ${ukey}, need upload!`);
const index = preRespData.upload.msgInfo.msgInfoBody[0].index; const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
const md5 = Buffer.from(index.info.fileHash, 'hex'); 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!`); this.logger.debug(`[Highway] uploadC2CVideoReq get upload invalid ukey ${ukey}, don't need upload!`);
} }
const subFile = preRespData.upload.subFileInfos[0]; 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!`); this.logger.debug(`[Highway] uploadC2CVideoReq get upload video thumb ukey: ${subFile.uKey}, need upload!`);
const index = preRespData.upload.msgInfo.msgInfoBody[1].index; const index = preRespData.upload.msgInfo.msgInfoBody[1].index;
const md5 = Buffer.from(index.info.fileHash, 'hex'); const md5 = Buffer.from(index.info.fileHash, 'hex');
@@ -345,7 +345,7 @@ export class PacketHighwayContext {
const resp = await this.client.sendOidbPacket(req, true); const resp = await this.client.sendOidbPacket(req, true);
const preRespData = trans.UploadGroupPtt.parse(resp); const preRespData = trans.UploadGroupPtt.parse(resp);
const ukey = preRespData.upload.uKey; const ukey = preRespData.upload.uKey;
if (ukey && ukey != "") { if (ukey && ukey != '') {
this.logger.debug(`[Highway] uploadGroupPttReq get upload ptt ukey: ${ukey}, need upload!`); this.logger.debug(`[Highway] uploadGroupPttReq get upload ptt ukey: ${ukey}, need upload!`);
const index = preRespData.upload.msgInfo.msgInfoBody[0].index; const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
const md5 = Buffer.from(index.info.fileHash, 'hex'); const md5 = Buffer.from(index.info.fileHash, 'hex');
@@ -381,7 +381,7 @@ export class PacketHighwayContext {
const resp = await this.client.sendOidbPacket(req, true); const resp = await this.client.sendOidbPacket(req, true);
const preRespData = trans.UploadPrivatePtt.parse(resp); const preRespData = trans.UploadPrivatePtt.parse(resp);
const ukey = preRespData.upload.uKey; const ukey = preRespData.upload.uKey;
if (ukey && ukey != "") { if (ukey && ukey != '') {
this.logger.debug(`[Highway] uploadC2CPttReq get upload ptt ukey: ${ukey}, need upload!`); this.logger.debug(`[Highway] uploadC2CPttReq get upload ptt ukey: ${ukey}, need upload!`);
const index = preRespData.upload.msgInfo.msgInfoBody[0].index; const index = preRespData.upload.msgInfo.msgInfoBody[0].index;
const md5 = Buffer.from(index.info.fileHash, 'hex'); const md5 = Buffer.from(index.info.fileHash, 'hex');
@@ -419,7 +419,7 @@ export class PacketHighwayContext {
const resp = await this.client.sendOidbPacket(req, true); const resp = await this.client.sendOidbPacket(req, true);
const preRespData = trans.UploadGroupFile.parse(resp); const preRespData = trans.UploadGroupFile.parse(resp);
if (!preRespData?.upload?.boolFileExist) { 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({ const ext = new NapProtoMsg(proto.FileUploadExt).encode({
unknown1: 100, unknown1: 100,
unknown2: 1, unknown2: 1,
@@ -439,9 +439,9 @@ export class PacketHighwayContext {
}, },
clientInfo: { clientInfo: {
clientType: 3, clientType: 3,
appId: "100", appId: '100',
terminalType: 3, terminalType: 3,
clientVer: "1.1.1", clientVer: '1.1.1',
unknown: 4 unknown: 4
}, },
fileNameInfo: { fileNameInfo: {
@@ -469,7 +469,7 @@ export class PacketHighwayContext {
ext ext
); );
} else { } 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; file.fileUuid = preRespData.upload.fileId;
} }
@@ -482,7 +482,7 @@ export class PacketHighwayContext {
const res = await this.client.sendOidbPacket(req, true); const res = await this.client.sendOidbPacket(req, true);
const preRespData = trans.UploadPrivateFile.parse(res); const preRespData = trans.UploadPrivateFile.parse(res);
if (!preRespData.upload?.boolFileExist) { 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({ const ext = new NapProtoMsg(proto.FileUploadExt).encode({
unknown1: 100, unknown1: 100,
unknown2: 1, unknown2: 1,
@@ -500,9 +500,9 @@ export class PacketHighwayContext {
}, },
clientInfo: { clientInfo: {
clientType: 3, clientType: 3,
appId: "100", appId: '100',
terminalType: 3, terminalType: 3,
clientVer: "1.1.1", clientVer: '1.1.1',
unknown: 4 unknown: 4
}, },
fileNameInfo: { fileNameInfo: {

View File

@@ -1,9 +1,9 @@
import crypto from "node:crypto"; import crypto from 'node:crypto';
import http from "node:http"; import http from 'node:http';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { IHighwayUploader } from "@/core/packet/highway/uploader/highwayUploader"; import { IHighwayUploader } from '@/core/packet/highway/uploader/highwayUploader';
import { Frame } from "@/core/packet/highway/frame"; import { Frame } from '@/core/packet/highway/frame';
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
export class HighwayHttpUploader extends IHighwayUploader { export class HighwayHttpUploader extends IHighwayUploader {
async upload(): Promise<void> { async upload(): Promise<void> {

View File

@@ -1,11 +1,11 @@
import net from "node:net"; import net from 'node:net';
import stream from "node:stream"; import stream from 'node:stream';
import crypto from "node:crypto"; import crypto from 'node:crypto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { BlockSize } from "@/core/packet/highway/highwayContext"; import { BlockSize } from '@/core/packet/highway/highwayContext';
import { Frame } from "@/core/packet/highway/frame"; import { Frame } from '@/core/packet/highway/frame';
import { IHighwayUploader } from "@/core/packet/highway/uploader/highwayUploader"; import { IHighwayUploader } from '@/core/packet/highway/uploader/highwayUploader';
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
class HighwayTcpUploaderTransform extends stream.Transform { class HighwayTcpUploaderTransform extends stream.Transform {
uploader: HighwayTcpUploader; uploader: HighwayTcpUploader;
@@ -17,7 +17,8 @@ class HighwayTcpUploaderTransform extends stream.Transform {
this.offset = 0; 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; let chunkOffset = 0;
while (chunkOffset < data.length) { while (chunkOffset < data.length) {
const chunkSize = Math.min(BlockSize, data.length - chunkOffset); const chunkSize = Math.min(BlockSize, data.length - chunkOffset);
@@ -60,6 +61,7 @@ export class HighwayTcpUploader extends IHighwayUploader {
socket.end(); socket.end();
reject(new Error('Upload aborted due to timeout')); reject(new Error('Upload aborted due to timeout'));
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [head, _] = Frame.unpack(chunk); const [head, _] = Frame.unpack(chunk);
handleRspHeader(head); handleRspHeader(head);
}); });

View File

@@ -1,8 +1,8 @@
import * as tea from "@/core/packet/utils/crypto/tea"; import * as tea from '@/core/packet/utils/crypto/tea';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { PacketHighwayTrans } from "@/core/packet/highway/client"; import { PacketHighwayTrans } from '@/core/packet/highway/client';
import { PacketLogger } from "@/core/packet/context/loggerContext"; import { PacketLogger } from '@/core/packet/context/loggerContext';
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
export abstract class IHighwayUploader { export abstract class IHighwayUploader {
readonly trans: PacketHighwayTrans; readonly trans: PacketHighwayTrans;
@@ -32,7 +32,7 @@ export abstract class IHighwayUploader {
msgBaseHead: { msgBaseHead: {
version: 1, version: 1,
uin: this.trans.uin, uin: this.trans.uin,
command: "PicUp.DataUp", command: 'PicUp.DataUp',
seq: 0, seq: 0,
retryTimes: 0, retryTimes: 0,
appId: 1600001604, appId: 1600001604,

View File

@@ -1,5 +1,5 @@
import { NapProtoEncodeStructType } from "@napneko/nap-proto-core"; import { NapProtoEncodeStructType } from '@napneko/nap-proto-core';
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
export const int32ip2str = (ip: number) => { export const int32ip2str = (ip: number) => {

View File

@@ -1,14 +1,14 @@
import * as crypto from "crypto"; import * as crypto from 'crypto';
import { PushMsgBody } from "@/core/packet/transformer/proto"; import { PushMsgBody } from '@/core/packet/transformer/proto';
import { NapProtoEncodeStructType } from "@napneko/nap-proto-core"; import { NapProtoEncodeStructType } from '@napneko/nap-proto-core';
import { PacketMsg, PacketSendMsgElement } from "@/core/packet/message/message"; import { PacketMsg, PacketSendMsgElement } from '@/core/packet/message/message';
import { IPacketMsgElement, PacketMsgTextElement } from "@/core/packet/message/element"; import { IPacketMsgElement, PacketMsgTextElement } from '@/core/packet/message/element';
import { SendTextElement } from "@/core"; import { SendTextElement } from '@/core';
export class PacketMsgBuilder { export class PacketMsgBuilder {
protected static failBackText = new PacketMsgTextElement( protected static failBackText = new PacketMsgTextElement(
{ {
textElement: { content: "[该消息类型暂不支持查看]" } textElement: { content: '[该消息类型暂不支持查看]' }
} as SendTextElement } as SendTextElement
); );
@@ -24,7 +24,7 @@ export class PacketMsgBuilder {
} }
return { return {
responseHead: { responseHead: {
fromUid: "", fromUid: '',
fromUin: node.senderUin, fromUin: node.senderUin,
toUid: node.groupId ? undefined : selfUid, toUid: node.groupId ? undefined : selfUid,
forward: node.groupId ? undefined : { forward: node.groupId ? undefined : {

View File

@@ -15,7 +15,7 @@ import {
SendStructLongMsgElement, SendStructLongMsgElement,
SendTextElement, SendTextElement,
SendVideoElement SendVideoElement
} from "@/core"; } from '@/core';
import { import {
IPacketMsgElement, IPacketMsgElement,
PacketMsgAtElement, PacketMsgAtElement,
@@ -30,8 +30,8 @@ import {
PacketMsgTextElement, PacketMsgTextElement,
PacketMsgVideoElement, PacketMsgVideoElement,
PacketMultiMsgElement PacketMultiMsgElement
} from "@/core/packet/message/element"; } from '@/core/packet/message/element';
import { PacketMsg, PacketSendMsgElement } from "@/core/packet/message/message"; import { PacketMsg, PacketSendMsgElement } from '@/core/packet/message/message';
const SupportedElementTypes = [ const SupportedElementTypes = [
ElementType.TEXT, ElementType.TEXT,
@@ -146,7 +146,7 @@ export class PacketMsgConverter {
? msg.sendMemberName ? msg.sendMemberName
: msg.sendNickName && msg.sendNickName !== '' : msg.sendNickName && msg.sendNickName !== ''
? msg.sendNickName ? msg.sendNickName
: "QQ用户", : 'QQ用户',
time: +msg.msgTime, time: +msg.msgTime,
msg: msg.elements.map((element) => { msg: msg.elements.map((element) => {
if (!this.isValidElementType(element.elementType)) return null; if (!this.isValidElementType(element.elementType)) return null;

View File

@@ -1,5 +1,5 @@
import * as zlib from "node:zlib"; import * as zlib from 'node:zlib';
import { NapProtoEncodeStructType, NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoEncodeStructType, NapProtoMsg } from '@napneko/nap-proto-core';
import { import {
CustomFace, CustomFace,
Elem, Elem,
@@ -12,9 +12,8 @@ import {
OidbSvcTrpcTcp0XE37_800Response, OidbSvcTrpcTcp0XE37_800Response,
FileExtra, FileExtra,
GroupFileExtra GroupFileExtra
} from "@/core/packet/transformer/proto"; } from '@/core/packet/transformer/proto';
import { import {
BaseEmojiType,
FaceType, FaceType,
NTMsgAtType, NTMsgAtType,
PicType, PicType,
@@ -29,14 +28,15 @@ import {
SendStructLongMsgElement, SendStructLongMsgElement,
SendTextElement, SendTextElement,
SendVideoElement SendVideoElement
} from "@/core"; } from '@/core';
import { ForwardMsgBuilder } from "@/common/forward-msg-builder"; import { ForwardMsgBuilder } from '@/common/forward-msg-builder';
import { PacketMsg, PacketSendMsgElement } from "@/core/packet/message/message"; import { PacketMsg, PacketSendMsgElement } from '@/core/packet/message/message';
// raw <-> packet // raw <-> packet
// TODO: SendStructLongMsgElement // TODO: SendStructLongMsgElement
export abstract class IPacketMsgElement<T extends PacketSendMsgElement> { 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 { get valid(): boolean {
@@ -64,7 +64,7 @@ export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> {
this.text = element.textElement.content; this.text = element.textElement.content;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{ return [{
text: { text: {
str: this.text str: this.text
@@ -72,7 +72,7 @@ export class PacketMsgTextElement extends IPacketMsgElement<SendTextElement> {
}]; }];
} }
toPreview(): string { override toPreview(): string {
return this.text; return this.text;
} }
} }
@@ -87,7 +87,7 @@ export class PacketMsgAtElement extends PacketMsgTextElement {
this.atAll = element.textElement.atType === NTMsgAtType.ATTYPEALL; this.atAll = element.textElement.atType === NTMsgAtType.ATTYPEALL;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{ return [{
text: { text: {
str: this.text, str: this.text,
@@ -127,7 +127,7 @@ export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
return this.messageClientSeq === 0; return this.messageClientSeq === 0;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{ return [{
srcMsg: { srcMsg: {
origSeqs: [this.isGroupReply ? this.messageClientSeq : this.messageSeq], origSeqs: [this.isGroupReply ? this.messageClientSeq : this.messageSeq],
@@ -152,8 +152,8 @@ export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
}]; }];
} }
toPreview(): string { override toPreview(): string {
return "[回复消息]"; return '[回复消息]';
} }
} }
@@ -169,18 +169,18 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
this.isLargeFace = element.faceElement.faceType === FaceType.AniSticke; this.isLargeFace = element.faceElement.faceType === FaceType.AniSticke;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
if (this.isLargeFace) { if (this.isLargeFace) {
return [{ return [{
commonElem: { commonElem: {
serviceType: 37, serviceType: 37,
pbElem: new NapProtoMsg(QBigFaceExtra).encode({ pbElem: new NapProtoMsg(QBigFaceExtra).encode({
aniStickerPackId: "1", aniStickerPackId: '1',
aniStickerId: "8", aniStickerId: '8',
faceId: this.faceId, faceId: this.faceId,
sourceType: 1, sourceType: 1,
resultId: this.resultId, resultId: this.resultId,
preview: "", preview: '',
randomType: 1 randomType: 1
}), }),
businessType: 1 businessType: 1
@@ -198,8 +198,8 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
serviceType: 33, serviceType: 33,
pbElem: new NapProtoMsg(QSmallFaceExtra).encode({ pbElem: new NapProtoMsg(QSmallFaceExtra).encode({
faceId: this.faceId, faceId: this.faceId,
preview: "", preview: '',
preview2: "" preview2: ''
}), }),
businessType: 1 businessType: 1
} }
@@ -207,8 +207,8 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
} }
} }
toPreview(): string { override toPreview(): string {
return "[表情]"; return '[表情]';
} }
} }
@@ -226,7 +226,7 @@ export class PacketMsgMarkFaceElement extends IPacketMsgElement<SendMarketFaceEl
this.emojiKey = element.marketFaceElement.key; this.emojiKey = element.marketFaceElement.key;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{ return [{
marketFace: { marketFace: {
faceName: this.emojiName, faceName: this.emojiName,
@@ -245,7 +245,7 @@ export class PacketMsgMarkFaceElement extends IPacketMsgElement<SendMarketFaceEl
}]; }];
} }
toPreview(): string { override toPreview(): string {
return `${this.emojiName}`; return `${this.emojiName}`;
} }
} }
@@ -280,11 +280,11 @@ export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
) : element.picElement.summary; ) : element.picElement.summary;
} }
get valid(): boolean { override get valid(): boolean {
return !!this.msgInfo; return !!this.msgInfo;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
if (!this.msgInfo) return []; if (!this.msgInfo) return [];
return [{ return [{
commonElem: { commonElem: {
@@ -295,7 +295,7 @@ export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
}]; }];
} }
toPreview(): string { override toPreview(): string {
return this.summary; return this.summary;
} }
} }
@@ -318,18 +318,18 @@ export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> {
this.fileSize = element.videoElement.fileSize; this.fileSize = element.videoElement.fileSize;
this.filePath = element.videoElement.filePath; this.filePath = element.videoElement.filePath;
this.thumbSize = element.videoElement.thumbSize; 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.fileMd5 = element.videoElement.videoMd5;
this.thumbMd5 = element.videoElement.thumbMd5; this.thumbMd5 = element.videoElement.thumbMd5;
this.thumbWidth = element.videoElement.thumbWidth; this.thumbWidth = element.videoElement.thumbWidth;
this.thumbHeight = element.videoElement.thumbHeight; this.thumbHeight = element.videoElement.thumbHeight;
} }
get valid(): boolean { override get valid(): boolean {
return !!this.msgInfo; return !!this.msgInfo;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
if (!this.msgInfo) return []; if (!this.msgInfo) return [];
return [{ return [{
commonElem: { commonElem: {
@@ -340,8 +340,8 @@ export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> {
}]; }];
} }
toPreview(): string { override toPreview(): string {
return "[视频]"; return '[视频]';
} }
} }
@@ -361,11 +361,11 @@ export class PacketMsgPttElement extends IPacketMsgElement<SendPttElement> {
this.fileDuration = Math.round(element.pttElement.duration); // TODO: cc this.fileDuration = Math.round(element.pttElement.duration); // TODO: cc
} }
get valid(): boolean { override get valid(): boolean {
return false; return false;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return []; return [];
// if (!this.msgInfo) return []; // if (!this.msgInfo) return [];
// return [{ // return [{
@@ -377,8 +377,8 @@ export class PacketMsgPttElement extends IPacketMsgElement<SendPttElement> {
// }]; // }];
} }
toPreview(): string { override toPreview(): string {
return "[语音]"; return '[语音]';
} }
} }
@@ -402,11 +402,11 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
this.fileSize = +element.fileElement.fileSize; this.fileSize = +element.fileElement.fileSize;
} }
get valid(): boolean { override get valid(): boolean {
return this.isGroupFile || Boolean(this._e37_800_rsp); return this.isGroupFile || Boolean(this._e37_800_rsp);
} }
buildContent(): Uint8Array | undefined { override buildContent(): Uint8Array | undefined {
if (this.isGroupFile || !this._e37_800_rsp) return undefined; if (this.isGroupFile || !this._e37_800_rsp) return undefined;
return new NapProtoMsg(FileExtra).encode({ return new NapProtoMsg(FileExtra).encode({
file: { file: {
@@ -437,7 +437,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
}); });
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
if (!this.isGroupFile) return []; if (!this.isGroupFile) return [];
const lb = Buffer.alloc(2); const lb = Buffer.alloc(2);
const transElemVal = new NapProtoMsg(GroupFileExtra).encode({ const transElemVal = new NapProtoMsg(GroupFileExtra).encode({
@@ -450,7 +450,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
fileSize: BigInt(this.fileSize), fileSize: BigInt(this.fileSize),
fileName: this.fileName, fileName: this.fileName,
fileSha: this.fileSha1, fileSha: this.fileSha1,
extInfoString: "", extInfoString: '',
fileMd5: this.fileMd5, fileMd5: this.fileMd5,
} }
} }
@@ -464,7 +464,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
}]; }];
} }
toPreview(): string { override toPreview(): string {
return `[文件]${this.fileName}`; return `[文件]${this.fileName}`;
} }
} }
@@ -477,7 +477,7 @@ export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement>
this.payload = element.arkElement.bytesData; this.payload = element.arkElement.bytesData;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{ return [{
lightAppElem: { lightAppElem: {
data: Buffer.concat([ data: Buffer.concat([
@@ -488,8 +488,8 @@ export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement>
}]; }];
} }
toPreview(): string { override toPreview(): string {
return "[卡片消息]"; return '[卡片消息]';
} }
} }
@@ -501,7 +501,7 @@ export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElem
this.content = element.markdownElement.content; this.content = element.markdownElement.content;
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{ return [{
commonElem: { commonElem: {
serviceType: 45, serviceType: 45,
@@ -513,7 +513,7 @@ export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElem
}]; }];
} }
toPreview(): string { override toPreview(): string {
return `[Markdown消息 ${this.content}]`; return `[Markdown消息 ${this.content}]`;
} }
} }
@@ -528,7 +528,7 @@ export class PacketMultiMsgElement extends IPacketMsgElement<SendStructLongMsgEl
this.message = message ?? []; this.message = message ?? [];
} }
buildElement(): NapProtoEncodeStructType<typeof Elem>[] { override buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return [{ return [{
lightAppElem: { lightAppElem: {
data: Buffer.concat([ data: Buffer.concat([
@@ -539,7 +539,7 @@ export class PacketMultiMsgElement extends IPacketMsgElement<SendStructLongMsgEl
}]; }];
} }
toPreview(): string { override toPreview(): string {
return "[聊天记录]"; return '[聊天记录]';
} }
} }

View File

@@ -1,5 +1,5 @@
import { IPacketMsgElement } from "@/core/packet/message/element"; import { IPacketMsgElement } from '@/core/packet/message/element';
import { SendMessageElement, SendStructLongMsgElement } from "@/core"; import { SendMessageElement, SendStructLongMsgElement } from '@/core';
export type PacketSendMsgElement = SendMessageElement | SendStructLongMsgElement export type PacketSendMsgElement = SendMessageElement | SendStructLongMsgElement

View File

@@ -1,8 +1,8 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import { AIVoiceChatType } from "@/core/packet/entities/aiChat"; import { AIVoiceChatType } from '@/core/packet/entities/aiChat';
class FetchAiVoiceList extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0X929D_0Resp> { class FetchAiVoiceList extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0X929D_0Resp> {
constructor() { constructor() {

View File

@@ -1,8 +1,8 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import { AIVoiceChatType } from "@/core/packet/entities/aiChat"; import { AIVoiceChatType } from '@/core/packet/entities/aiChat';
class GetAiVoice extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0X929B_0Resp> { class GetAiVoice extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0X929B_0Resp> {
constructor() { constructor() {

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from '@/core/packet/transformer/base';
import { MiniAppReqParams } from "@/core/packet/entities/miniApp"; import { MiniAppReqParams } from '@/core/packet/entities/miniApp';
class GetMiniAppAdaptShareInfo extends PacketTransformer<typeof proto.MiniAppAdaptShareInfoResp> { class GetMiniAppAdaptShareInfo extends PacketTransformer<typeof proto.MiniAppAdaptShareInfoResp> {
constructor() { constructor() {
@@ -23,24 +23,24 @@ class GetMiniAppAdaptShareInfo extends PacketTransformer<typeof proto.MiniAppAda
templateType: req.templateType, templateType: req.templateType,
businessType: req.businessType, businessType: req.businessType,
picUrl: req.picUrl, picUrl: req.picUrl,
vidUrl: "", vidUrl: '',
jumpUrl: req.jumpUrl, jumpUrl: req.jumpUrl,
iconUrl: req.iconUrl, iconUrl: req.iconUrl,
verType: req.verType, verType: req.verType,
shareType: req.shareType, shareType: req.shareType,
versionId: req.versionId, versionId: req.versionId,
withShareTicket: req.withShareTicket, withShareTicket: req.withShareTicket,
webURL: req.webUrl ?? "", webURL: req.webUrl ?? '',
appidRich: Buffer.alloc(0), appidRich: Buffer.alloc(0),
template: { template: {
templateId: "", templateId: '',
templateData: "" templateData: ''
}, },
field20: "" field20: ''
} }
}); });
return { return {
cmd: "LightAppSvc.mini_app_share.AdaptShareInfo", cmd: 'LightAppSvc.mini_app_share.AdaptShareInfo',
data: PacketHexStrBuilder(data) data: PacketHexStrBuilder(data)
}; };
} }

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class GetStrangerInfo extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XFE1_2RSP> { class GetStrangerInfo extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XFE1_2RSP> {
constructor() { constructor() {

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class GroupSign extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> { class GroupSign extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
constructor() { constructor() {
@@ -14,7 +14,7 @@ class GroupSign extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
body: { body: {
uin: String(uin), uin: String(uin),
groupUin: String(groupCode), groupUin: String(groupCode),
version: "9.0.90" version: '9.0.90'
} }
} }
); );

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class ImageOCR extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0xE07_0_Response> { class ImageOCR extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0xE07_0_Response> {
constructor() { constructor() {
@@ -16,11 +16,11 @@ class ImageOCR extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0xE07_0_Resp
entrance: 1, entrance: 1,
ocrReqBody: { ocrReqBody: {
imageUrl: url, imageUrl: url,
originMd5: "", originMd5: '',
afterCompressMd5: "", afterCompressMd5: '',
afterCompressFileSize: "", afterCompressFileSize: '',
afterCompressWeight: "", afterCompressWeight: '',
afterCompressHeight: "", afterCompressHeight: '',
isCut: false, isCut: false,
} }
} }

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class SendPoke extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> { class SendPoke extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
constructor() { constructor() {

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class SetSpecialTitle extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> { class SetSpecialTitle extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
constructor() { constructor() {

View File

@@ -1,5 +1,5 @@
import { NapProtoDecodeStructType } from "@napneko/nap-proto-core"; import { NapProtoDecodeStructType } from '@napneko/nap-proto-core';
import { PacketMsgBuilder } from "@/core/packet/message/builder"; import { PacketMsgBuilder } from '@/core/packet/message/builder';
export type PacketHexStr = string & { readonly hexNya: unique symbol }; export type PacketHexStr = string & { readonly hexNya: unique symbol };

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class DownloadGroupFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0x6D6Response> { class DownloadGroupFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0x6D6Response> {
constructor() { constructor() {

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoEncodeStructType, NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoEncodeStructType, NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class DownloadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> { class DownloadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
constructor() { constructor() {

View File

@@ -1,8 +1,8 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoEncodeStructType, NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoEncodeStructType, NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import { IndexNode } from "@/core/packet/transformer/proto"; import { IndexNode } from '@/core/packet/transformer/proto';
class DownloadImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> { class DownloadImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
constructor() { constructor() {

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class DownloadOfflineFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37Response> { class DownloadOfflineFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37Response> {
constructor() { constructor() {

View File

@@ -1,7 +1,7 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
class DownloadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37_1200Response> { class DownloadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37_1200Response> {
constructor() { constructor() {

View File

@@ -1,6 +1,6 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from '@/core/packet/transformer/base';
class FetchSessionKey extends PacketTransformer<typeof proto.HttpConn0x6ff_501Response> { class FetchSessionKey extends PacketTransformer<typeof proto.HttpConn0x6ff_501Response> {
constructor() { constructor() {
@@ -20,11 +20,11 @@ class FetchSessionKey extends PacketTransformer<typeof proto.HttpConn0x6ff_501Re
field9: 2, field9: 2,
field10: 9, field10: 9,
field11: 8, field11: 8,
ver: "1.0.1" ver: '1.0.1'
} }
}); });
return { return {
cmd: "HttpConn.0x6ff_501", cmd: 'HttpConn.0x6ff_501',
data: PacketHexStrBuilder(req) data: PacketHexStrBuilder(req)
}; };
} }

View File

@@ -1,8 +1,8 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import { PacketMsgFileElement } from "@/core/packet/message/element"; import { PacketMsgFileElement } from '@/core/packet/message/element';
class UploadGroupFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0x6D6Response> { class UploadGroupFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0x6D6Response> {
constructor() { constructor() {

View File

@@ -1,9 +1,9 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import crypto from "node:crypto"; import crypto from 'node:crypto';
import { PacketMsgPicElement } from "@/core/packet/message/element"; import { PacketMsgPicElement } from '@/core/packet/message/element';
class UploadGroupImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> { class UploadGroupImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
constructor() { constructor() {

View File

@@ -1,9 +1,9 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import crypto from "node:crypto"; import crypto from 'node:crypto';
import { PacketMsgPttElement } from "@/core/packet/message/element"; import { PacketMsgPttElement } from '@/core/packet/message/element';
class UploadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> { class UploadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
constructor() { constructor() {
@@ -57,7 +57,7 @@ class UploadGroupPtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
compatQMsgSceneType: 2, compatQMsgSceneType: 2,
extBizInfo: { extBizInfo: {
pic: { pic: {
textSummary: "Nya~", textSummary: 'Nya~',
}, },
video: { video: {
bytesPbReserve: Buffer.alloc(0), bytesPbReserve: Buffer.alloc(0),

View File

@@ -1,9 +1,9 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import crypto from "node:crypto"; import crypto from 'node:crypto';
import { PacketMsgVideoElement } from "@/core/packet/message/element"; import { PacketMsgVideoElement } from '@/core/packet/message/element';
class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> { class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
constructor() { constructor() {
@@ -11,7 +11,7 @@ class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp>
} }
build(groupUin: number, video: PacketMsgVideoElement): OidbPacket { 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({ const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
reqHead: { reqHead: {
common: { common: {
@@ -37,7 +37,7 @@ class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp>
fileSize: +video.fileSize, fileSize: +video.fileSize,
fileHash: video.fileMd5, fileHash: video.fileMd5,
fileSha1: video.fileSha1, fileSha1: video.fileSha1,
fileName: "nya.mp4", fileName: 'nya.mp4',
type: { type: {
type: 2, type: 2,
picFormat: 0, picFormat: 0,
@@ -55,7 +55,7 @@ class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp>
fileSize: +video.thumbSize, fileSize: +video.thumbSize,
fileHash: video.thumbMd5, fileHash: video.thumbMd5,
fileSha1: video.thumbSha1, fileSha1: video.thumbSha1,
fileName: "nya.jpg", fileName: 'nya.jpg',
type: { type: {
type: 1, type: 1,
picFormat: 0, picFormat: 0,
@@ -77,7 +77,7 @@ class UploadGroupVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp>
extBizInfo: { extBizInfo: {
pic: { pic: {
bizType: 0, bizType: 0,
textSummary: "Nya~", textSummary: 'Nya~',
}, },
video: { video: {
bytesPbReserve: Buffer.from([0x80, 0x01, 0x00]), bytesPbReserve: Buffer.from([0x80, 0x01, 0x00]),

View File

@@ -1,9 +1,9 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import { PacketMsgFileElement } from "@/core/packet/message/element"; import { PacketMsgFileElement } from '@/core/packet/message/element';
import { computeMd5AndLengthWithLimit } from "@/core/packet/utils/crypto/hash"; import { computeMd5AndLengthWithLimit } from '@/core/packet/utils/crypto/hash';
class UploadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37Response> { class UploadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE37Response> {
constructor() { constructor() {
@@ -21,7 +21,7 @@ class UploadPrivateFile extends PacketTransformer<typeof proto.OidbSvcTrpcTcp0XE
fileName: file.fileName, fileName: file.fileName,
md510MCheckSum: await computeMd5AndLengthWithLimit(file.filePath, 10 * 1024 * 1024), md510MCheckSum: await computeMd5AndLengthWithLimit(file.filePath, 10 * 1024 * 1024),
sha1CheckSum: file.fileSha1, sha1CheckSum: file.fileSha1,
localPath: "/", localPath: '/',
md5CheckSum: file.fileMd5, md5CheckSum: file.fileMd5,
sha3CheckSum: Buffer.alloc(0) sha3CheckSum: Buffer.alloc(0)
}, },

View File

@@ -1,9 +1,9 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import crypto from "node:crypto"; import crypto from 'node:crypto';
import { PacketMsgPicElement } from "@/core/packet/message/element"; import { PacketMsgPicElement } from '@/core/packet/message/element';
class UploadPrivateImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> { class UploadPrivateImage extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
constructor() { constructor() {

View File

@@ -1,9 +1,9 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import crypto from "node:crypto"; import crypto from 'node:crypto';
import { PacketMsgPttElement } from "@/core/packet/message/element"; import { PacketMsgPttElement } from '@/core/packet/message/element';
class UploadPrivatePtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> { class UploadPrivatePtt extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
constructor() { constructor() {
@@ -58,7 +58,7 @@ class UploadPrivatePtt extends PacketTransformer<typeof proto.NTV2RichMediaResp>
compatQMsgSceneType: 1, compatQMsgSceneType: 1,
extBizInfo: { extBizInfo: {
pic: { pic: {
textSummary: "Nya~", textSummary: 'Nya~',
}, },
ptt: { ptt: {
bytesReserve: Buffer.from([0x08, 0x00, 0x38, 0x00]), bytesReserve: Buffer.from([0x08, 0x00, 0x38, 0x00]),

View File

@@ -1,9 +1,9 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketTransformer } from '@/core/packet/transformer/base';
import OidbBase from "@/core/packet/transformer/oidb/oidbBase"; import OidbBase from '@/core/packet/transformer/oidb/oidbBase';
import crypto from "node:crypto"; import crypto from 'node:crypto';
import { PacketMsgVideoElement } from "@/core/packet/message/element"; import { PacketMsgVideoElement } from '@/core/packet/message/element';
class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> { class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaResp> {
constructor() { constructor() {
@@ -11,7 +11,7 @@ class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaRes
} }
build(peerUin: string, video: PacketMsgVideoElement): OidbPacket { 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({ const data = new NapProtoMsg(proto.NTV2RichMediaReq).encode({
reqHead: { reqHead: {
common: { common: {
@@ -38,7 +38,7 @@ class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaRes
fileSize: +video.fileSize, fileSize: +video.fileSize,
fileHash: video.fileMd5, fileHash: video.fileMd5,
fileSha1: video.fileSha1, fileSha1: video.fileSha1,
fileName: "nya.mp4", fileName: 'nya.mp4',
type: { type: {
type: 2, type: 2,
picFormat: 0, picFormat: 0,
@@ -56,7 +56,7 @@ class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaRes
fileSize: +video.thumbSize, fileSize: +video.thumbSize,
fileHash: video.thumbMd5, fileHash: video.thumbMd5,
fileSha1: video.thumbSha1, fileSha1: video.thumbSha1,
fileName: "nya.jpg", fileName: 'nya.jpg',
type: { type: {
type: 1, type: 1,
picFormat: 0, picFormat: 0,
@@ -78,7 +78,7 @@ class UploadPrivateVideo extends PacketTransformer<typeof proto.NTV2RichMediaRes
extBizInfo: { extBizInfo: {
pic: { pic: {
bizType: 0, bizType: 0,
textSummary: "Nya~", textSummary: 'Nya~',
}, },
video: { video: {
bytesPbReserve: Buffer.from([0x80, 0x01, 0x00]), bytesPbReserve: Buffer.from([0x80, 0x01, 0x00]),

View File

@@ -1,8 +1,8 @@
import zlib from "node:zlib"; import zlib from 'node:zlib';
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from '@/core/packet/transformer/base';
import { PacketMsg } from "@/core/packet/message/message"; import { PacketMsg } from '@/core/packet/message/message';
class UploadForwardMsg extends PacketTransformer<typeof proto.SendLongMsgResp> { class UploadForwardMsg extends PacketTransformer<typeof proto.SendLongMsgResp> {
constructor() { constructor() {
@@ -14,7 +14,7 @@ class UploadForwardMsg extends PacketTransformer<typeof proto.SendLongMsgResp> {
const longMsgResultData = new NapProtoMsg(proto.LongMsgResult).encode( const longMsgResultData = new NapProtoMsg(proto.LongMsgResult).encode(
{ {
action: { action: {
actionCommand: "MultiMsg", actionCommand: 'MultiMsg',
actionData: { actionData: {
msgBody: msgBody msgBody: msgBody
} }
@@ -38,7 +38,7 @@ class UploadForwardMsg extends PacketTransformer<typeof proto.SendLongMsgResp> {
} }
); );
return { return {
cmd: "trpc.group.long_msg_interface.MsgService.SsoSendLongMsg", cmd: 'trpc.group.long_msg_interface.MsgService.SsoSendLongMsg',
data: PacketHexStrBuilder(req) data: PacketHexStrBuilder(req)
}; };
} }

View File

@@ -1,6 +1,6 @@
import * as proto from "@/core/packet/transformer/proto"; import * as proto from '@/core/packet/transformer/proto';
import { NapProtoMsg } from "@napneko/nap-proto-core"; import { NapProtoMsg } from '@napneko/nap-proto-core';
import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from "@/core/packet/transformer/base"; import { OidbPacket, PacketHexStrBuilder, PacketTransformer } from '@/core/packet/transformer/base';
class OidbBase extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> { class OidbBase extends PacketTransformer<typeof proto.OidbSvcTrpcTcpBase> {
constructor() { constructor() {

View File

@@ -1,6 +1,6 @@
import { ScalarType } from "@protobuf-ts/runtime"; import { ScalarType } from '@protobuf-ts/runtime';
import { ProtoField } from "@napneko/nap-proto-core"; import { ProtoField } from '@napneko/nap-proto-core';
import { ContentHead, MessageBody, MessageControl, RoutingHead } from "@/core/packet/transformer/proto"; import { ContentHead, MessageBody, MessageControl, RoutingHead } from '@/core/packet/transformer/proto';
export const FaceRoamRequest = { export const FaceRoamRequest = {
comm: ProtoField(1, () => PlatInfo, true), comm: ProtoField(1, () => PlatInfo, true),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const MiniAppAdaptShareInfoReq = { export const MiniAppAdaptShareInfoReq = {
appId: ProtoField(2, ScalarType.STRING), appId: ProtoField(2, ScalarType.STRING),

View File

@@ -1,5 +1,5 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
import { MsgInfoBody } from "@/core/packet/transformer/proto"; import { MsgInfoBody } from '@/core/packet/transformer/proto';
export const DataHighwayHead = { export const DataHighwayHead = {
version: ProtoField(1, ScalarType.UINT32), version: ProtoField(1, ScalarType.UINT32),

View File

@@ -1,32 +1,32 @@
// action folder // action folder
export * from "./action/action"; export * from './action/action';
export * from "./action/miniAppAdaptShareInfo"; export * from './action/miniAppAdaptShareInfo';
// highway folder // highway folder
export * from "./highway/highway"; export * from './highway/highway';
// message folder // message folder
export * from "./message/action"; export * from './message/action';
export * from "./message/c2c"; export * from './message/c2c';
export * from "./message/component"; export * from './message/component';
export * from "./message/element"; export * from './message/element';
export * from "./message/group"; export * from './message/group';
export * from "./message/message"; export * from './message/message';
export * from "./message/notify"; export * from './message/notify';
export * from "./message/routing"; export * from './message/routing';
// oidb folder // oidb folder
export * from "./oidb/common/Ntv2.RichMediaReq"; export * from './oidb/common/Ntv2.RichMediaReq';
export * from "./oidb/common/Ntv2.RichMediaResp"; export * from './oidb/common/Ntv2.RichMediaResp';
export * from "./oidb/Oidb.0x6D6"; export * from './oidb/Oidb.0x6D6';
export * from "./oidb/Oidb.0x8FC_2"; export * from './oidb/Oidb.0x8FC_2';
export * from "./oidb/Oidb.0x9067_202"; export * from './oidb/Oidb.0x9067_202';
export * from "./oidb/Oidb.0x929"; export * from './oidb/Oidb.0x929';
export * from "./oidb/Oidb.0xE37_1200"; export * from './oidb/Oidb.0xE37_1200';
export * from "./oidb/Oidb.0xE37_1700"; export * from './oidb/Oidb.0xE37_1700';
export * from "./oidb/Oidb.0XE37_800"; export * from './oidb/Oidb.0XE37_800';
export * from "./oidb/Oidb.0xEB7"; export * from './oidb/Oidb.0xEB7';
export * from "./oidb/Oidb.0xED3_1"; export * from './oidb/Oidb.0xED3_1';
export * from "./oidb/Oidb.0XFE1_2"; export * from './oidb/Oidb.0XFE1_2';
export * from "./oidb/OidbBase"; export * from './oidb/OidbBase';
export * from "./oidb/Oidb.0xE07"; export * from './oidb/Oidb.0xE07';

View File

@@ -1,5 +1,5 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
import { PushMsgBody } from "@/core/packet/transformer/proto"; import { PushMsgBody } from '@/core/packet/transformer/proto';
export const LongMsgResult = { export const LongMsgResult = {
action: ProtoField(2, () => LongMsgAction) action: ProtoField(2, () => LongMsgAction)

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const C2C = { export const C2C = {
uin: ProtoField(1, ScalarType.UINT32, true), uin: ProtoField(1, ScalarType.UINT32, true),

View File

@@ -1,5 +1,5 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
import { Elem } from "@/core/packet/transformer/proto"; import { Elem } from '@/core/packet/transformer/proto';
export const Attr = { export const Attr = {
codePage: ProtoField(1, ScalarType.INT32), codePage: ProtoField(1, ScalarType.INT32),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const Elem = { export const Elem = {
text: ProtoField(1, () => Text, true), text: ProtoField(1, () => Text, true),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const GroupRecallMsg = { export const GroupRecallMsg = {
type: ProtoField(1, ScalarType.UINT32), type: ProtoField(1, ScalarType.UINT32),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const GroupAdminExtra = { export const GroupAdminExtra = {
adminUid: ProtoField(1, ScalarType.STRING), adminUid: ProtoField(1, ScalarType.STRING),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
import { import {
C2C, C2C,
ForwardHead, ForwardHead,
@@ -8,7 +8,7 @@ import {
ResponseGrp, RichText, ResponseGrp, RichText,
Trans0X211, Trans0X211,
WPATmp WPATmp
} from "@/core/packet/transformer/proto"; } from '@/core/packet/transformer/proto';
export const ContentHead = { export const ContentHead = {
type: ProtoField(1, ScalarType.UINT32), type: ProtoField(1, ScalarType.UINT32),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const FriendRecall = { export const FriendRecall = {
info: ProtoField(1, () => FriendRecallInfo), info: ProtoField(1, () => FriendRecallInfo),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const ForwardHead = { export const ForwardHead = {
field1: ProtoField(1, ScalarType.UINT32, true), field1: ProtoField(1, ScalarType.UINT32, true),

View File

@@ -1,5 +1,5 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
import { OidbSvcTrpcTcp0XE37_800_1200Metadata } from "@/core/packet/transformer/proto"; import { OidbSvcTrpcTcp0XE37_800_1200Metadata } from '@/core/packet/transformer/proto';
export const OidbSvcTrpcTcp0XE37_800 = { export const OidbSvcTrpcTcp0XE37_800 = {
subCommand: ProtoField(1, ScalarType.UINT32), subCommand: ProtoField(1, ScalarType.UINT32),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const OidbSvcTrpcTcp0XFE1_2 = { export const OidbSvcTrpcTcp0XFE1_2 = {
uin: ProtoField(1, ScalarType.UINT32), uin: ProtoField(1, ScalarType.UINT32),

View File

@@ -1,4 +1,4 @@
import { ProtoField, ScalarType } from "@napneko/nap-proto-core"; import { ProtoField, ScalarType } from '@napneko/nap-proto-core';
export const OidbSvcTrpcTcp0x6D6 = { export const OidbSvcTrpcTcp0x6D6 = {
file: ProtoField(1, () => OidbSvcTrpcTcp0x6D6Upload, true), file: ProtoField(1, () => OidbSvcTrpcTcp0x6D6Upload, true),

Some files were not shown because too many files have changed in this diff Show More