diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..b413ff63 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,52 @@ +import neostandard from 'neostandard'; + +/** 尾随逗号 */ +const commaDangle = val => { + if (val?.rules?.['@stylistic/comma-dangle']?.[0] === 'warn') { + const rule = val?.rules?.['@stylistic/comma-dangle']?.[1]; + Object.keys(rule).forEach(key => { + rule[key] = 'always-multiline'; + }); + val.rules['@stylistic/comma-dangle'][1] = rule; + } + + /** 三元表达式 */ + if (val?.rules?.['@stylistic/indent']) { + val.rules['@stylistic/indent'][2] = { + ...val.rules?.['@stylistic/indent']?.[2], + flatTernaryExpressions: true, + offsetTernaryExpressions: false, + }; + } + + /** 支持下划线 - 禁用 camelcase 规则 */ + if (val?.rules?.camelcase) { + val.rules.camelcase = 'off'; + } + + /** 未使用的变量强制报错 */ + if (val?.rules?.['@typescript-eslint/no-unused-vars']) { + val.rules['@typescript-eslint/no-unused-vars'] = ['error', { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }]; + } + + return val; +}; + +/** 忽略的文件 */ +const ignores = [ + 'node_modules', + '**/dist/**', + 'launcher', +]; + +const options = neostandard({ + ts: true, + ignores, + semi: true, // 强制使用分号 +}).map(commaDangle); + +export default options; diff --git a/package.json b/package.json index 295ee533..3c38cd5a 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,17 @@ "dev:shell": "pnpm --filter napcat-develop run dev || exit 1", "typecheck": "pnpm -r --if-present run typecheck", "test": "pnpm --filter napcat-test run test", - "test:ui": "pnpm --filter napcat-test run test:ui" + "test:ui": "pnpm --filter napcat-test run test:ui", + "lint": "eslint .", + "lint:fix": "eslint . --fix" }, "devDependencies": { "@rollup/plugin-node-resolve": "^16.0.3", "@vitejs/plugin-react-swc": "^4.2.2", "@vitest/ui": "^4.0.9", + "eslint": "^9.39.1", "inversify": "^7.10.4", + "neostandard": "^0.12.2", "reflect-metadata": "^0.2.2", "typescript": "^5.3.0", "vite": "^6.4.1", diff --git a/packages/napcat-common/src/helper.ts b/packages/napcat-common/src/helper.ts index 093e9df1..c1809c0c 100644 --- a/packages/napcat-common/src/helper.ts +++ b/packages/napcat-common/src/helper.ts @@ -3,7 +3,7 @@ import fs from 'fs'; import os from 'node:os'; import { QQVersionConfigType, QQLevel } from './types'; -export async function solveProblem any>(func: T, ...args: Parameters): Promise | undefined> { +export async function solveProblem any> (func: T, ...args: Parameters): Promise | undefined> { return new Promise | undefined>((resolve) => { try { const result = func(...args); @@ -14,7 +14,7 @@ export async function solveProblem any>(func: T, .. }); } -export async function solveAsyncProblem Promise>(func: T, ...args: Parameters): Promise> | undefined> { +export async function solveAsyncProblem Promise> (func: T, ...args: Parameters): Promise> | undefined> { return new Promise> | undefined>((resolve) => { func(...args).then((result) => { resolve(result); @@ -24,18 +24,18 @@ export async function solveAsyncProblem Promise { +export function sleep (ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } -export function PromiseTimer(promise: Promise, ms: number): Promise { +export function PromiseTimer (promise: Promise, ms: number): Promise { const timeoutPromise = new Promise((_resolve, reject) => setTimeout(() => reject(new Error('PromiseTimer: Operation timed out')), ms) ); return Promise.race([promise, timeoutPromise]); } -export async function runAllWithTimeout(tasks: Promise[], timeout: number): Promise { +export async function runAllWithTimeout (tasks: Promise[], timeout: number): Promise { const wrappedTasks = tasks.map((task) => PromiseTimer(task, timeout).then( (result) => ({ status: 'fulfilled', value: result }), @@ -48,15 +48,15 @@ export async function runAllWithTimeout(tasks: Promise[], timeout: number) .map((result) => (result as { status: 'fulfilled'; value: T; }).value); } -export function isNull(value: any) { +export function isNull (value: any) { return value === undefined || value === null; } -export function isNumeric(str: string) { +export function isNumeric (str: string) { return /^\d+$/.test(str); } -export function truncateString(obj: any, maxLength = 500) { +export function truncateString (obj: any, maxLength = 500) { if (obj !== null && typeof obj === 'object') { Object.keys(obj).forEach((key) => { if (typeof obj[key] === 'string') { @@ -73,7 +73,7 @@ export function truncateString(obj: any, maxLength = 500) { return obj; } -export function isEqual(obj1: any, obj2: any) { +export function isEqual (obj1: any, obj2: any) { if (obj1 === obj2) return true; if (obj1 == null || obj2 == null) return false; if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return obj1 === obj2; @@ -89,7 +89,7 @@ export function isEqual(obj1: any, obj2: any) { return true; } -export function getDefaultQQVersionConfigInfo(): QQVersionConfigType { +export function getDefaultQQVersionConfigInfo (): QQVersionConfigType { if (os.platform() === 'linux') { return { baseVersion: '3.2.12.28060', @@ -117,7 +117,7 @@ export function getDefaultQQVersionConfigInfo(): QQVersionConfigType { }; } -export function getQQPackageInfoPath(exePath: string = '', version?: string): string { +export function getQQPackageInfoPath (exePath: string = '', version?: string): string { if (process.env['NAPCAT_QQ_PACKAGE_INFO_PATH']) { return process.env['NAPCAT_QQ_PACKAGE_INFO_PATH']; } @@ -136,7 +136,7 @@ export function getQQPackageInfoPath(exePath: string = '', version?: string): st return packagePath; } -export function getQQVersionConfigPath(exePath: string = ''): string | undefined { +export function getQQVersionConfigPath (exePath: string = ''): string | undefined { if (process.env['NAPCAT_QQ_VERSION_CONFIG_PATH']) { return process.env['NAPCAT_QQ_VERSION_CONFIG_PATH']; } @@ -165,7 +165,7 @@ export function getQQVersionConfigPath(exePath: string = ''): string | undefined return configVersionInfoPath; } -export function calcQQLevel(level?: QQLevel) { +export function calcQQLevel (level?: QQLevel) { if (!level) return 0; // const { penguinNum, crownNum, sunNum, moonNum, starNum } = level; const { crownNum, sunNum, moonNum, starNum } = level; @@ -173,13 +173,13 @@ export function calcQQLevel(level?: QQLevel) { return crownNum * 64 + sunNum * 16 + moonNum * 4 + starNum; } -export function stringifyWithBigInt(obj: any) { +export function stringifyWithBigInt (obj: any) { return JSON.stringify(obj, (_key, 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 sequenceBytes = Buffer.from(hexSequence.replace(/ /g, ''), 'hex'); const filePath = path.resolve(nodeMajor); diff --git a/packages/napcat-common/src/store.ts b/packages/napcat-common/src/store.ts index 9d804f28..9b5e3baa 100644 --- a/packages/napcat-common/src/store.ts +++ b/packages/napcat-common/src/store.ts @@ -19,4 +19,4 @@ class Store { const store = new Store(); -export default store; \ No newline at end of file +export default store; diff --git a/packages/napcat-common/src/types.ts b/packages/napcat-common/src/types.ts index d2442788..17652a7d 100644 --- a/packages/napcat-common/src/types.ts +++ b/packages/napcat-common/src/types.ts @@ -25,4 +25,4 @@ export interface QQLevel { sunNum: number; moonNum: number; starNum: number; -} \ No newline at end of file +} diff --git a/packages/napcat-common/src/version.ts b/packages/napcat-common/src/version.ts index b1afab9c..e798ba8a 100644 --- a/packages/napcat-common/src/version.ts +++ b/packages/napcat-common/src/version.ts @@ -1,3 +1,2 @@ // @ts-ignore export const napCatVersion = (typeof import.meta?.env !== 'undefined' && import.meta.env.VITE_NAPCAT_VERSION) || 'alpha'; - diff --git a/packages/napcat-core/adapters/NodeIDependsAdapter.ts b/packages/napcat-core/adapters/NodeIDependsAdapter.ts index b65b6d54..1f37c2a4 100644 --- a/packages/napcat-core/adapters/NodeIDependsAdapter.ts +++ b/packages/napcat-core/adapters/NodeIDependsAdapter.ts @@ -24,4 +24,4 @@ export class NodeIDependsAdapter { // console.log('[NodeIDependsAdapter] onSendMsfReply', _seq, _cmd, _uk1, _uk2, Buffer.from(_rsp.pbBuffer).toString('hex')); // } -} \ No newline at end of file +} diff --git a/packages/napcat-core/apis/file.ts b/packages/napcat-core/apis/file.ts index 4817e55a..e45ebf70 100644 --- a/packages/napcat-core/apis/file.ts +++ b/packages/napcat-core/apis/file.ts @@ -33,7 +33,7 @@ export class NTQQFileApi { 'http://ss.xingzhige.com/music_card/rkey', 'https://secret-service.bietiaop.com/rkeys', ], - this.context.logger + this.context.logger ); } @@ -169,7 +169,6 @@ export class NTQQFileApi { }; } - async downloadFileForModelId (peer: Peer, modelId: string, unknown: string, timeout = 1000 * 60 * 2) { const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2( 'NodeIKernelRichMediaService/downloadFileForModelId', diff --git a/packages/napcat-core/helper/event.ts b/packages/napcat-core/helper/event.ts index 1579dfce..7da4b1ee 100644 --- a/packages/napcat-core/helper/event.ts +++ b/packages/napcat-core/helper/event.ts @@ -25,18 +25,18 @@ export class NTEventWrapper { private readonly listenerManager: Map = new Map(); // ListenerName-Unique -> Listener实例 private readonly EventTask = new Map>>(); // tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func} - constructor( + constructor ( wrapperSession: NodeIQQNTWrapperSession ) { this.WrapperSession = wrapperSession; } - createProxyDispatch(ListenerMainName: string) { + createProxyDispatch (ListenerMainName: string) { const dispatcherListenerFunc = this.dispatcherListener.bind(this); return new Proxy( {}, { - get(target: any, prop: any, receiver: any) { + get (target: any, prop: any, receiver: any) { if (typeof target[prop] === 'undefined') { // 如果方法不存在,返回一个函数,这个函数调用existentMethod return (...args: any[]) => { @@ -94,7 +94,7 @@ export class NTEventWrapper { } // 统一回调清理事件 - async dispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: any[]) { + async dispatcherListener (ListenerMainName: string, ListenerSubName: string, ...args: any[]) { this.EventTask.get(ListenerMainName) ?.get(ListenerSubName) ?.forEach((task, uuid) => { @@ -137,7 +137,7 @@ export class NTEventWrapper { let complete = 0; let retData: Parameters | undefined; - function sendDataCallback() { + function sendDataCallback () { if (complete === 0) { reject(new Error(' ListenerName:' + listenerAndMethod + ' timeout')); } else { @@ -191,7 +191,7 @@ export class NTEventWrapper { let retData: Parameters | undefined; let retEvent: any = {}; - function sendDataCallback(resolve: any, reject: any) { + function sendDataCallback (resolve: any, reject: any) { if (complete === 0) { reject( new Error( diff --git a/packages/napcat-core/helper/ffmpeg/ffmpeg-addon-adapter.ts b/packages/napcat-core/helper/ffmpeg/ffmpeg-addon-adapter.ts index c2154e16..3f131511 100644 --- a/packages/napcat-core/helper/ffmpeg/ffmpeg-addon-adapter.ts +++ b/packages/napcat-core/helper/ffmpeg/ffmpeg-addon-adapter.ts @@ -68,13 +68,13 @@ export class FFmpegAddonAdapter implements IFFmpegAdapter { const addon = this.ensureAddon(); const info = await addon.getVideoInfo(videoPath); - let format = info.format.includes(',') ? info.format.split(',')[0] ?? info.format : info.format; + const format = info.format.includes(',') ? info.format.split(',')[0] ?? info.format : info.format; console.log('[FFmpegAddonAdapter] Detected format:', format); return { width: info.width, height: info.height, duration: info.duration, - format: format, + format, thumbnail: info.image, }; } diff --git a/packages/napcat-core/helper/ffmpeg/ffmpeg.ts b/packages/napcat-core/helper/ffmpeg/ffmpeg.ts index ee56a99b..f8cbee44 100644 --- a/packages/napcat-core/helper/ffmpeg/ffmpeg.ts +++ b/packages/napcat-core/helper/ffmpeg/ffmpeg.ts @@ -53,7 +53,6 @@ export class FFmpegService { throw new Error('FFmpeg service not initialized. Please call FFmpegService.init() first.'); } return this.adapter.name; - } /** diff --git a/packages/napcat-core/index.ts b/packages/napcat-core/index.ts index e67c9b2c..57a47c2c 100644 --- a/packages/napcat-core/index.ts +++ b/packages/napcat-core/index.ts @@ -45,7 +45,7 @@ export enum NapCatCoreWorkingEnv { Framework = 2, } -export function loadQQWrapper(QQVersion: string): WrapperNodeApi { +export function loadQQWrapper (QQVersion: string): WrapperNodeApi { if (process.env['NAPCAT_WRAPPER_PATH']) { const wrapperPath = process.env['NAPCAT_WRAPPER_PATH']; const nativemodule: { exports: WrapperNodeApi; } = { exports: {} as WrapperNodeApi }; @@ -72,7 +72,7 @@ export function loadQQWrapper(QQVersion: string): WrapperNodeApi { process.dlopen(nativemodule, wrapperNodePath); return nativemodule.exports; } -export function getMajorPath(QQVersion: string): string { +export function getMajorPath (QQVersion: string): string { // major.node let appPath; if (os.platform() === 'darwin') { @@ -105,7 +105,7 @@ export class NapCatCore { configLoader: NapCatConfigLoader; // 通过构造器递过去的 runtime info 应该尽量少 - constructor(context: InstanceContext, selfInfo: SelfInfo) { + constructor (context: InstanceContext, selfInfo: SelfInfo) { this.selfInfo = selfInfo; this.context = context; this.util = this.context.wrapper.NodeQQNTWrapperUtil; @@ -134,7 +134,7 @@ export class NapCatCore { }); } - async initCore() { + async initCore () { this.NapCatDataPath = path.join(this.dataPath, 'NapCat'); fs.mkdirSync(this.NapCatDataPath, { recursive: true }); this.NapCatTempPath = path.join(this.NapCatDataPath, 'temp'); @@ -163,7 +163,7 @@ export class NapCatCore { ); } - get dataPath(): string { + get dataPath (): string { let result = this.context.wrapper.NodeQQNTWrapperUtil.getNTUserDataInfoConfig(); if (!result) { result = path.resolve(os.homedir(), './.config/QQ'); @@ -173,7 +173,7 @@ export class NapCatCore { } // Renamed from 'InitDataListener' - async initNapCatCoreListeners() { + async initNapCatCoreListeners () { const msgListener = new NodeIKernelMsgListener(); msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => { @@ -211,7 +211,7 @@ export class NapCatCore { } } -export async function genSessionConfig( +export async function genSessionConfig ( guid: string, QQVersionAppid: string, QQVersion: string, diff --git a/packages/napcat-core/packet/context/loggerContext.ts b/packages/napcat-core/packet/context/loggerContext.ts index 737aa619..a867f80c 100644 --- a/packages/napcat-core/packet/context/loggerContext.ts +++ b/packages/napcat-core/packet/context/loggerContext.ts @@ -1,4 +1,3 @@ - import { NapCoreContext } from '@/napcat-core/packet/context/napCoreContext'; import { LogWrapper, LogLevel } from '@/napcat-core/helper/log'; diff --git a/packages/napcat-core/packet/handler/client.ts b/packages/napcat-core/packet/handler/client.ts index 8f907bc0..48854b7b 100644 --- a/packages/napcat-core/packet/handler/client.ts +++ b/packages/napcat-core/packet/handler/client.ts @@ -50,7 +50,6 @@ export class NativePacketHandler { this.logger.logError('NativePacketClient 加载出错:', error); this.loaded = false; } - } /** diff --git a/packages/napcat-core/packet/handler/eventList.ts b/packages/napcat-core/packet/handler/eventList.ts index 265d7c66..e0e09312 100644 --- a/packages/napcat-core/packet/handler/eventList.ts +++ b/packages/napcat-core/packet/handler/eventList.ts @@ -1,6 +1,6 @@ -import { TypedEventEmitter } from "./typeEvent"; +import { TypedEventEmitter } from './typeEvent'; export interface AppEvents { - 'event:emoji_like': { groupId: string; senderUin: string; emojiId: string, msgSeq: string, isAdd: boolean,count:number }; + 'event:emoji_like': { groupId: string; senderUin: string; emojiId: string, msgSeq: string, isAdd: boolean, count: number }; } -export const appEvent = new TypedEventEmitter(); \ No newline at end of file +export const appEvent = new TypedEventEmitter(); diff --git a/packages/napcat-core/packet/handler/serviceRegister.ts b/packages/napcat-core/packet/handler/serviceRegister.ts index 196ff85e..f03a830f 100644 --- a/packages/napcat-core/packet/handler/serviceRegister.ts +++ b/packages/napcat-core/packet/handler/serviceRegister.ts @@ -1,28 +1,28 @@ -import "reflect-metadata"; -import { Container, injectable } from "inversify"; -import { NapCatCore } from "../.."; -import { TypedEventEmitter } from "./typeEvent"; +import 'reflect-metadata'; +import { Container, injectable } from 'inversify'; +import { NapCatCore } from '../..'; +import { TypedEventEmitter } from './typeEvent'; export const container = new Container(); export const ReceiverServiceRegistry = new Map ServiceBase>(); export abstract class ServiceBase { - get core(): NapCatCore { - return container.get(NapCatCore); - } - get event() { - return container.get(TypedEventEmitter); - } + get core (): NapCatCore { + return container.get(NapCatCore); + } - abstract handler(seq: number, hex_data: string): Promise | void; + get event () { + return container.get(TypedEventEmitter); + } + + abstract handler (seq: number, hex_data: string): Promise | void; } -export function ReceiveService(serviceName: string) { - return function ServiceBase>(constructor: T) { - injectable()(constructor); - ReceiverServiceRegistry.set(serviceName, constructor); - return constructor; - }; +export function ReceiveService (serviceName: string) { + return function ServiceBase>(constructor: T) { + injectable()(constructor); + ReceiverServiceRegistry.set(serviceName, constructor); + return constructor; + }; } - diff --git a/packages/napcat-core/protocol/OlpushSerivce.ts b/packages/napcat-core/protocol/OlpushSerivce.ts index 7fa518e4..6bb54413 100644 --- a/packages/napcat-core/protocol/OlpushSerivce.ts +++ b/packages/napcat-core/protocol/OlpushSerivce.ts @@ -1,37 +1,36 @@ -import { NapProtoMsg } from "napcat-protobuf"; -import { ReceiveService, ServiceBase } from "../packet/handler/serviceRegister"; -import { GroupReactNotify, PushMsg } from "../packet/transformer/proto"; +import { NapProtoMsg } from 'napcat-protobuf'; +import { ReceiveService, ServiceBase } from '../packet/handler/serviceRegister'; +import { GroupReactNotify, PushMsg } from '../packet/transformer/proto'; @ReceiveService('trpc.msg.olpush.OlPushService.MsgPush') export class OlPushService extends ServiceBase { - async handler(_seq: number, hex_data: string) { - const data = new NapProtoMsg(PushMsg).decode(Buffer.from(hex_data, 'hex')); - if (data.message.contentHead.type === 732 && data.message.contentHead.subType === 16) { - const pbNotify = data.message.body?.msgContent?.slice(7); - if (!pbNotify) { - return; - } - // 开始解析Notify - const notify = new NapProtoMsg(GroupReactNotify).decode(pbNotify); - if ((notify.field13 ?? 0) === 35) { - // Group React Notify - const groupCode = notify.groupUin?.toString() ?? ''; - const operatorUid = notify.groupReactionData?.data?.data?.groupReactionDataContent?.operatorUid ?? ''; - const type = notify.groupReactionData?.data?.data?.groupReactionDataContent?.type ?? 0; - const seq = notify.groupReactionData?.data?.data?.groupReactionTarget?.seq?.toString() ?? ''; - const code = notify.groupReactionData?.data?.data?.groupReactionDataContent?.code ?? ''; - const count = notify.groupReactionData?.data?.data?.groupReactionDataContent?.count ?? 0; - const senderUin = await this.core.apis.UserApi.getUinByUidV2(operatorUid); - this.event.emit('event:emoji_like', { - groupId: groupCode, - senderUin: senderUin, - emojiId: code, - msgSeq: seq, - isAdd: type === 1, - count: count - }); - } - } - + async handler (_seq: number, hex_data: string) { + const data = new NapProtoMsg(PushMsg).decode(Buffer.from(hex_data, 'hex')); + if (data.message.contentHead.type === 732 && data.message.contentHead.subType === 16) { + const pbNotify = data.message.body?.msgContent?.slice(7); + if (!pbNotify) { + return; + } + // 开始解析Notify + const notify = new NapProtoMsg(GroupReactNotify).decode(pbNotify); + if ((notify.field13 ?? 0) === 35) { + // Group React Notify + const groupCode = notify.groupUin?.toString() ?? ''; + const operatorUid = notify.groupReactionData?.data?.data?.groupReactionDataContent?.operatorUid ?? ''; + const type = notify.groupReactionData?.data?.data?.groupReactionDataContent?.type ?? 0; + const seq = notify.groupReactionData?.data?.data?.groupReactionTarget?.seq?.toString() ?? ''; + const code = notify.groupReactionData?.data?.data?.groupReactionDataContent?.code ?? ''; + const count = notify.groupReactionData?.data?.data?.groupReactionDataContent?.count ?? 0; + const senderUin = await this.core.apis.UserApi.getUinByUidV2(operatorUid); + this.event.emit('event:emoji_like', { + groupId: groupCode, + senderUin, + emojiId: code, + msgSeq: seq, + isAdd: type === 1, + count, + }); + } } -} \ No newline at end of file + } +} diff --git a/packages/napcat-core/services/NodeIKernelBuddyService.ts b/packages/napcat-core/services/NodeIKernelBuddyService.ts index 32c4fdd7..880f9232 100644 --- a/packages/napcat-core/services/NodeIKernelBuddyService.ts +++ b/packages/napcat-core/services/NodeIKernelBuddyService.ts @@ -24,7 +24,6 @@ export interface NodeIKernelBuddyService { }>; }>; - getBuddyListFromCache (reqType: BuddyListReqType): Promise | Array> }> = object > = { - [P in K]: - S[P] extends Array + [P in K]: + S[P] extends Array ? Pick, U & keyof NonNullable> : S[P] extends keyof NonNullable - ? Pick, S[P]> - : NonNullable; - }; + ? Pick, S[P]> + : NonNullable; +}; export interface TextElement { content: string; diff --git a/packages/napcat-develop/index.js b/packages/napcat-develop/index.js index 2c5488b1..98c9defe 100644 --- a/packages/napcat-develop/index.js +++ b/packages/napcat-develop/index.js @@ -10,5 +10,5 @@ const NAPCAT_MJS_PATH = path.join(BASE_DIR, 'napcat', 'napcat.mjs'); process.env.NAPCAT_WRAPPER_PATH = WRAPPER_NODE_PATH; process.env.NAPCAT_QQ_PACKAGE_INFO_PATH = PACKAGE_JSON_PATH; process.env.NAPCAT_QQ_VERSION_CONFIG_PATH = CONFIG_JSON_PATH; - process.env.NAPCAT_DISABLE_PIPE = '1'; -import(pathToFileURL(NAPCAT_MJS_PATH).href); \ No newline at end of file +process.env.NAPCAT_DISABLE_PIPE = '1'; +import(pathToFileURL(NAPCAT_MJS_PATH).href); diff --git a/packages/napcat-develop/loadNapCat.cjs b/packages/napcat-develop/loadNapCat.cjs index 88c60d02..aa58889a 100644 --- a/packages/napcat-develop/loadNapCat.cjs +++ b/packages/napcat-develop/loadNapCat.cjs @@ -33,7 +33,7 @@ const BASE_DIR = path.join(versionsDir, selectedFolder, 'resources', 'app'); console.log(`BASE_DIR: ${BASE_DIR}`); const TARGET_DIR = path.join(__dirname, 'dist'); const QQNT_FILE = path.join(__dirname, 'QQNT.dll'); -const NAPCAT_MJS_PATH = path.join(__dirname, '..', 'napcat-shell','dist', 'napcat.mjs'); +const NAPCAT_MJS_PATH = path.join(__dirname, '..', 'napcat-shell', 'dist', 'napcat.mjs'); const itemsToCopy = [ 'avif_convert.dll', @@ -45,15 +45,15 @@ const itemsToCopy = [ 'opencv.dll', 'package.json', 'QBar.dll', - 'wrapper.node' + 'wrapper.node', ]; async function copyAll () { const qqntDllPath = path.join(TARGET_DIR, 'QQNT.dll'); const configPath = path.join(TARGET_DIR, 'config.json'); - const allItemsExist = await fs.pathExists(qqntDllPath) - && await fs.pathExists(configPath) - && (await Promise.all(itemsToCopy.map(item => fs.pathExists(path.join(TARGET_DIR, item))))).every(exists => exists); + const allItemsExist = await fs.pathExists(qqntDllPath) && + await fs.pathExists(configPath) && + (await Promise.all(itemsToCopy.map(item => fs.pathExists(path.join(TARGET_DIR, item))))).every(exists => exists); if (!allItemsExist) { console.log('Copying required files...'); @@ -79,4 +79,4 @@ async function copyAll () { await import(pathToFileURL(NAPCAT_MJS_PATH).href); } -copyAll().catch(console.error); \ No newline at end of file +copyAll().catch(console.error); diff --git a/packages/napcat-framework/vite.config.ts b/packages/napcat-framework/vite.config.ts index 6ada540d..9e4121a1 100644 --- a/packages/napcat-framework/vite.config.ts +++ b/packages/napcat-framework/vite.config.ts @@ -2,23 +2,23 @@ import cp from 'vite-plugin-cp'; import { defineConfig, PluginOption, UserConfig } from 'vite'; import path, { resolve } from 'path'; import nodeResolve from '@rollup/plugin-node-resolve'; -import { autoIncludeTSPlugin } from "napcat-vite/vite-auto-include.js"; +import { autoIncludeTSPlugin } from 'napcat-vite/vite-auto-include.js'; import { builtinModules } from 'module'; import react from '@vitejs/plugin-react-swc'; -import napcatVersion from "napcat-vite/vite-plugin-version.js"; -//依赖排除 +import napcatVersion from 'napcat-vite/vite-plugin-version.js'; +// 依赖排除 const external = [ 'silk-wasm', 'ws', - 'express' + 'express', ]; const nodeModules = [...builtinModules, builtinModules.map((m) => `node:${m}`)].flat(); const FrameworkBaseConfigPlugin: PluginOption[] = [ autoIncludeTSPlugin({ entries: [ { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-core/protocol') }, - { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') } - ] + { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') }, + ], }), react({ tsDecorators: true }), cp({ diff --git a/packages/napcat-onebot/action/auto-register.ts b/packages/napcat-onebot/action/auto-register.ts index 90a3fa61..705ca023 100644 --- a/packages/napcat-onebot/action/auto-register.ts +++ b/packages/napcat-onebot/action/auto-register.ts @@ -1,6 +1,6 @@ import { OneBotAction } from './OneBotAction'; export const AutoRegisterRouter: Array OneBotAction> = []; -export function ActionHandler(target: new (...args: any[]) => OneBotAction) { - AutoRegisterRouter.push(target); +export function ActionHandler (target: new (...args: any[]) => OneBotAction) { + AutoRegisterRouter.push(target); } diff --git a/packages/napcat-onebot/action/index.ts b/packages/napcat-onebot/action/index.ts index 1c80890b..562b44e8 100644 --- a/packages/napcat-onebot/action/index.ts +++ b/packages/napcat-onebot/action/index.ts @@ -138,7 +138,7 @@ import { TestDownloadStream } from './stream/TestStreamDownload'; import { UploadFileStream } from './stream/UploadFileStream'; import { AutoRegisterRouter } from './auto-register'; -export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore) { +export function createActionMap (obContext: NapCatOneBot11Adapter, core: NapCatCore) { const actionHandlers = [ new CleanStreamTempFile(obContext, core), new DownloadFileStream(obContext, core), @@ -315,7 +315,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo // function get(key: K): MapType[K]; // function get(key: K): null; // function get(key: K): HandlerUnion | null | MapType[K] - function get(key: K): MapType[K] | undefined { + function get (key: K): MapType[K] | undefined { return _map.get(key as keyof MapType) as MapType[K] | undefined; } return { get }; diff --git a/packages/napcat-onebot/api/file.ts b/packages/napcat-onebot/api/file.ts index 0f9b2949..a7b2d094 100644 --- a/packages/napcat-onebot/api/file.ts +++ b/packages/napcat-onebot/api/file.ts @@ -1,5 +1,3 @@ - - import { NapCatOneBot11Adapter } from '@/napcat-onebot/index'; import { encodeSilk } from '@/napcat-core/helper/audio'; import { FFmpegService } from '@/napcat-core/helper/ffmpeg/ffmpeg'; @@ -14,169 +12,169 @@ import fsPromises from 'fs/promises'; import fs from 'fs'; import { defaultVideoThumbB64 } from '@/napcat-core/helper/ffmpeg/video'; export class OneBotFileApi { - obContext: NapCatOneBot11Adapter; - core: NapCatCore; - constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) { - this.obContext = obContext; - this.core = core; + obContext: NapCatOneBot11Adapter; + core: NapCatCore; + constructor (obContext: NapCatOneBot11Adapter, core: NapCatCore) { + this.obContext = obContext; + this.core = core; + } + + async createValidSendFileElement (context: SendMessageContext, filePath: string, fileName: string = '', folderId: string = ''): Promise { + const { + fileName: _fileName, + path, + fileSize, + } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.FILE); + if (fileSize === 0) { + throw new Error('文件异常,大小为0'); } - async createValidSendFileElement(context: SendMessageContext, filePath: string, fileName: string = '', folderId: string = ''): Promise { - const { - fileName: _fileName, - path, - fileSize, - } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.FILE); - if (fileSize === 0) { - throw new Error('文件异常,大小为0'); - } - context.deleteAfterSentFiles.push(path); - return { - elementType: ElementType.FILE, - elementId: '', - fileElement: { - fileName: fileName || _fileName, - folderId, - filePath: path, - fileSize: fileSize.toString(), - }, - }; + context.deleteAfterSentFiles.push(path); + return { + elementType: ElementType.FILE, + elementId: '', + fileElement: { + fileName: fileName || _fileName, + folderId, + filePath: path, + fileSize: fileSize.toString(), + }, + }; + } + + async createValidSendPicElement (context: SendMessageContext, picPath: string, summary: string = '', subType: PicSubType = 0): Promise { + const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType); + if (fileSize === 0) { + throw new Error('文件异常,大小为0'); } + const imageSize = await imageSizeFallBack(picPath); + context.deleteAfterSentFiles.push(path); + return { + elementType: ElementType.PIC, + elementId: '', + picElement: { + md5HexStr: md5, + fileSize: fileSize.toString(), + picWidth: imageSize.width, + picHeight: imageSize.height, + fileName, + sourcePath: path, + original: true, + picType: await getFileTypeForSendType(picPath), + picSubType: subType, + fileUuid: '', + fileSubId: '', + thumbFileSize: 0, + summary, + } as PicElement, + }; + } - async createValidSendPicElement(context: SendMessageContext, picPath: string, summary: string = '', subType: PicSubType = 0): Promise { - const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType); - if (fileSize === 0) { - throw new Error('文件异常,大小为0'); - } - const imageSize = await imageSizeFallBack(picPath); - context.deleteAfterSentFiles.push(path); - return { - elementType: ElementType.PIC, - elementId: '', - picElement: { - md5HexStr: md5, - fileSize: fileSize.toString(), - picWidth: imageSize.width, - picHeight: imageSize.height, - fileName, - sourcePath: path, - original: true, - picType: await getFileTypeForSendType(picPath), - picSubType: subType, - fileUuid: '', - fileSubId: '', - thumbFileSize: 0, - summary, - } as PicElement, - }; + async createValidSendVideoElement (context: SendMessageContext, filePath: string, fileName: string = '', _diyThumbPath: string = ''): Promise { + let videoInfo = { + width: 1920, + height: 1080, + time: 15, + format: 'mp4', + size: 0, + filePath, + }; + let fileExt = 'mp4'; + try { + const tempExt = (await fileTypeFromFile(filePath))?.ext; + if (tempExt) fileExt = tempExt; + } catch (e) { + this.core.context.logger.logError('获取文件类型失败', e); } + const newFilePath = `${filePath}.${fileExt}`; + fs.copyFileSync(filePath, newFilePath); + context.deleteAfterSentFiles.push(newFilePath); + filePath = newFilePath; - async createValidSendVideoElement(context: SendMessageContext, filePath: string, fileName: string = '', _diyThumbPath: string = ''): Promise { - let videoInfo = { - width: 1920, - height: 1080, - time: 15, - format: 'mp4', - size: 0, - filePath, - }; - let fileExt = 'mp4'; - try { - const tempExt = (await fileTypeFromFile(filePath))?.ext; - if (tempExt) fileExt = tempExt; - } catch (e) { - this.core.context.logger.logError('获取文件类型失败', e); - } - const newFilePath = `${filePath}.${fileExt}`; - fs.copyFileSync(filePath, newFilePath); - context.deleteAfterSentFiles.push(newFilePath); - filePath = newFilePath; - - const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO); - context.deleteAfterSentFiles.push(path); - if (fileSize === 0) { - throw new Error('文件异常,大小为0'); - } - const thumbDir = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`); - fs.mkdirSync(pathLib.dirname(thumbDir), { recursive: true }); - const thumbPath = pathLib.join(pathLib.dirname(thumbDir), `${md5}_0.png`); - try { - videoInfo = await FFmpegService.getVideoInfo(filePath, thumbPath); - if (!fs.existsSync(thumbPath)) { - this.core.context.logger.logError('获取视频缩略图失败', new Error('缩略图不存在')); - throw new Error('获取视频缩略图失败'); - } - } catch (e) { - this.core.context.logger.logError('获取视频信息失败', e); - fs.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64')); - } - if (_diyThumbPath) { - try { - await this.core.apis.FileApi.copyFile(_diyThumbPath, thumbPath); - } catch (e) { - this.core.context.logger.logError('复制自定义缩略图失败', e); - } - } - context.deleteAfterSentFiles.push(thumbPath); - const thumbSize = (await fsPromises.stat(thumbPath)).size; - const thumbMd5 = await calculateFileMD5(thumbPath); - context.deleteAfterSentFiles.push(thumbPath); - - const uploadName = (fileName || _fileName).toLocaleLowerCase().endsWith(`.${fileExt.toLocaleLowerCase()}`) ? (fileName || _fileName) : `${fileName || _fileName}.${fileExt}`; - return { - elementType: ElementType.VIDEO, - elementId: '', - videoElement: { - fileName: uploadName, - filePath: path, - videoMd5: md5, - thumbMd5, - fileTime: videoInfo.time, - thumbPath: new Map([[0, thumbPath]]), - thumbSize, - thumbWidth: videoInfo.width, - thumbHeight: videoInfo.height, - fileSize: fileSize.toString(), - }, - }; + const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO); + context.deleteAfterSentFiles.push(path); + if (fileSize === 0) { + throw new Error('文件异常,大小为0'); } - - async createValidSendPttElement(_context: SendMessageContext, pttPath: string): Promise { - const { converted, path: silkPath, duration } = await encodeSilk(pttPath, this.core.NapCatTempPath, this.core.context.logger); - if (!silkPath) { - throw new Error('语音转换失败, 请检查语音文件是否正常'); - } - const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(silkPath, ElementType.PTT); - if (fileSize === 0) { - throw new Error('文件异常,大小为0'); - } - if (converted) { - fsPromises.unlink(silkPath).then().catch((e) => this.core.context.logger.logError('删除临时文件失败', e)); - } - return { - elementType: ElementType.PTT, - elementId: '', - pttElement: { - fileName, - filePath: path, - md5HexStr: md5, - fileSize: fileSize.toString(), - duration: duration ?? 1, - formatType: 1, - voiceType: 1, - voiceChangeType: 0, - canConvert2Text: true, - waveAmplitudes: [ - 0, 18, 9, 23, 16, 17, 16, 15, 44, 17, 24, 20, 14, 15, 17, - ], - fileSubId: '', - playState: 1, - autoConvertText: 0, - storeID: 0, - otherBusinessInfo: { - aiVoiceType: 0, - }, - }, - }; + const thumbDir = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`); + fs.mkdirSync(pathLib.dirname(thumbDir), { recursive: true }); + const thumbPath = pathLib.join(pathLib.dirname(thumbDir), `${md5}_0.png`); + try { + videoInfo = await FFmpegService.getVideoInfo(filePath, thumbPath); + if (!fs.existsSync(thumbPath)) { + this.core.context.logger.logError('获取视频缩略图失败', new Error('缩略图不存在')); + throw new Error('获取视频缩略图失败'); + } + } catch (e) { + this.core.context.logger.logError('获取视频信息失败', e); + fs.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64')); } + if (_diyThumbPath) { + try { + await this.core.apis.FileApi.copyFile(_diyThumbPath, thumbPath); + } catch (e) { + this.core.context.logger.logError('复制自定义缩略图失败', e); + } + } + context.deleteAfterSentFiles.push(thumbPath); + const thumbSize = (await fsPromises.stat(thumbPath)).size; + const thumbMd5 = await calculateFileMD5(thumbPath); + context.deleteAfterSentFiles.push(thumbPath); + const uploadName = (fileName || _fileName).toLocaleLowerCase().endsWith(`.${fileExt.toLocaleLowerCase()}`) ? (fileName || _fileName) : `${fileName || _fileName}.${fileExt}`; + return { + elementType: ElementType.VIDEO, + elementId: '', + videoElement: { + fileName: uploadName, + filePath: path, + videoMd5: md5, + thumbMd5, + fileTime: videoInfo.time, + thumbPath: new Map([[0, thumbPath]]), + thumbSize, + thumbWidth: videoInfo.width, + thumbHeight: videoInfo.height, + fileSize: fileSize.toString(), + }, + }; + } + + async createValidSendPttElement (_context: SendMessageContext, pttPath: string): Promise { + const { converted, path: silkPath, duration } = await encodeSilk(pttPath, this.core.NapCatTempPath, this.core.context.logger); + if (!silkPath) { + throw new Error('语音转换失败, 请检查语音文件是否正常'); + } + const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(silkPath, ElementType.PTT); + if (fileSize === 0) { + throw new Error('文件异常,大小为0'); + } + if (converted) { + fsPromises.unlink(silkPath).then().catch((e) => this.core.context.logger.logError('删除临时文件失败', e)); + } + return { + elementType: ElementType.PTT, + elementId: '', + pttElement: { + fileName, + filePath: path, + md5HexStr: md5, + fileSize: fileSize.toString(), + duration: duration ?? 1, + formatType: 1, + voiceType: 1, + voiceChangeType: 0, + canConvert2Text: true, + waveAmplitudes: [ + 0, 18, 9, 23, 16, 17, 16, 15, 44, 17, 24, 20, 14, 15, 17, + ], + fileSubId: '', + playState: 1, + autoConvertText: 0, + storeID: 0, + otherBusinessInfo: { + aiVoiceType: 0, + }, + }, + }; + } } diff --git a/packages/napcat-onebot/api/group.ts b/packages/napcat-onebot/api/group.ts index d18e2f14..c5164c06 100644 --- a/packages/napcat-onebot/api/group.ts +++ b/packages/napcat-onebot/api/group.ts @@ -30,12 +30,12 @@ import { NapCatOneBot11Adapter } from '..'; export class OneBotGroupApi { obContext: NapCatOneBot11Adapter; core: NapCatCore; - constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) { + constructor (obContext: NapCatOneBot11Adapter, core: NapCatCore) { this.obContext = obContext; this.core = core; } - async parseGroupBanEvent(GroupCode: string, grayTipElement: GrayTipElement) { + async parseGroupBanEvent (GroupCode: string, grayTipElement: GrayTipElement) { const groupElement = grayTipElement?.groupElement; if (!groupElement?.shutUp) return undefined; const memberUid = groupElement.shutUp.member.uid; @@ -66,7 +66,7 @@ export class OneBotGroupApi { return undefined; } - async parseGroupEmojiLikeEventByGrayTip( + async parseGroupEmojiLikeEventByGrayTip ( groupCode: string, grayTipElement: GrayTipElement ) { @@ -85,7 +85,7 @@ export class OneBotGroupApi { return await this.createGroupEmojiLikeEvent(groupCode, senderUin, msgSeq, emojiId, true, 1); } - async createGroupEmojiLikeEvent( + async createGroupEmojiLikeEvent ( groupCode: string, senderUin: string, msgSeq: string, @@ -121,7 +121,7 @@ export class OneBotGroupApi { ); } - async parseCardChangedEvent(msg: RawMessage) { + async parseCardChangedEvent (msg: RawMessage) { if (msg.senderUin && msg.senderUin !== '0') { const member = await this.core.apis.GroupApi.getGroupMember(msg.peerUid, msg.senderUin); if (member && member.cardName !== msg.sendMemberName) { @@ -137,7 +137,7 @@ export class OneBotGroupApi { return undefined; } - async registerParseGroupReactEvent() { + async registerParseGroupReactEvent () { this.obContext.core.context.packetHandler.onCmd('trpc.msg.olpush.OlPushService.MsgPush', async (packet) => { const data = new NapProtoMsg(PushMsg).decode(Buffer.from(packet.hex_data, 'hex')); if (data.message.contentHead.type === 732 && data.message.contentHead.subType === 16) { @@ -172,7 +172,7 @@ export class OneBotGroupApi { }); } - async registerParseGroupReactEventByCore() { + async registerParseGroupReactEventByCore () { this.core.event.on('event:emoji_like', async (data) => { console.log('Received emoji_like event from core:', data); const event = await this.createGroupEmojiLikeEvent( @@ -188,7 +188,8 @@ export class OneBotGroupApi { } }); } - async parsePaiYiPai(msg: RawMessage, jsonStr: string) { + + async parsePaiYiPai (msg: RawMessage, jsonStr: string) { const json = JSON.parse(jsonStr); // 判断业务类型 // Poke事件 @@ -207,7 +208,7 @@ export class OneBotGroupApi { return undefined; } - async parseOtherJsonEvent(msg: RawMessage, jsonStr: string, context: InstanceContext) { + async parseOtherJsonEvent (msg: RawMessage, jsonStr: string, context: InstanceContext) { const json = JSON.parse(jsonStr); const type = json.items[json.items.length - 1]?.txt; await this.core.apis.GroupApi.refreshGroupMemberCachePartial(msg.peerUid, msg.senderUid); @@ -229,7 +230,7 @@ export class OneBotGroupApi { return undefined; } - async parseEssenceMsg(msg: RawMessage, jsonStr: string) { + async parseEssenceMsg (msg: RawMessage, jsonStr: string) { const json = JSON.parse(jsonStr); const searchParams = new URL(json.items[0].jp).searchParams; const msgSeq = searchParams.get('msgSeq')!; @@ -257,7 +258,7 @@ export class OneBotGroupApi { // 获取MsgSeq+Peer可获取具体消息 } - async parseGroupUploadFileEvene(msg: RawMessage, element: FileElement, elementWrapper: MessageElement) { + async parseGroupUploadFileEvene (msg: RawMessage, element: FileElement, elementWrapper: MessageElement) { return new OB11GroupUploadNoticeEvent( this.core, parseInt(msg.peerUid), parseInt(msg.senderUin || ''), @@ -273,7 +274,7 @@ export class OneBotGroupApi { ); } - async parseGroupElement(msg: RawMessage, element: TipGroupElement, elementWrapper: GrayTipElement) { + async parseGroupElement (msg: RawMessage, element: TipGroupElement, elementWrapper: GrayTipElement) { if (element.type === TipGroupElementType.KGROUPNAMEMODIFIED) { this.core.context.logger.logDebug('收到群名称变更事件', element); return new OB11GroupNameEvent( @@ -301,7 +302,7 @@ export class OneBotGroupApi { return undefined; } - async parseSelfInviteEvent(msg: RawMessage, inviterUin: string, inviteeUin: string) { + async parseSelfInviteEvent (msg: RawMessage, inviterUin: string, inviteeUin: string) { return new OB11GroupIncreaseEvent( this.core, parseInt(msg.peerUid), @@ -311,7 +312,7 @@ export class OneBotGroupApi { ); } - async parse51TypeEvent(msg: RawMessage, grayTipElement: GrayTipElement) { + async parse51TypeEvent (msg: RawMessage, grayTipElement: GrayTipElement) { // 神经腾讯 没了妈妈想出来的 // Warn 下面存在高并发危险 if (grayTipElement.jsonGrayTipElement.jsonStr) { @@ -340,7 +341,7 @@ export class OneBotGroupApi { return undefined; } - async parseGrayTipElement(msg: RawMessage, grayTipElement: GrayTipElement) { + async parseGrayTipElement (msg: RawMessage, grayTipElement: GrayTipElement) { if (grayTipElement.subElementType === NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_GROUP) { // 解析群组事件 由sysmsg解析 return await this.parseGroupElement(msg, grayTipElement.groupElement, grayTipElement); diff --git a/packages/napcat-onebot/index.ts b/packages/napcat-onebot/index.ts index 6952a6bf..4fd656d0 100644 --- a/packages/napcat-onebot/index.ts +++ b/packages/napcat-onebot/index.ts @@ -75,7 +75,7 @@ export class NapCatOneBot11Adapter { actions: ActionMap; private readonly bootTime = Date.now() / 1000; recallEventCache = new Map(); - constructor(core: NapCatCore, context: InstanceContext, pathWrapper: NapCatPathWrapper) { + constructor (core: NapCatCore, context: InstanceContext, pathWrapper: NapCatPathWrapper) { this.core = core; this.context = context; this.configLoader = new OB11ConfigLoader(core, pathWrapper.configPath, OneBotConfigSchema); @@ -91,7 +91,7 @@ export class NapCatOneBot11Adapter { this.networkManager = new OB11NetworkManager(); } - async creatOneBotLog(ob11Config: OneBotConfig) { + async creatOneBotLog (ob11Config: OneBotConfig) { let log = '[network] 配置加载\n'; for (const key of ob11Config.network.httpServers) { log += `HTTP服务: ${key.host}:${key.port}, : ${key.enable ? '已启动' : '未启动'}\n`; @@ -111,7 +111,7 @@ export class NapCatOneBot11Adapter { return log; } - async InitOneBot() { + async InitOneBot () { const selfInfo = this.core.selfInfo; const ob11Config = this.configLoader.configData; this.core.apis.UserApi.getUserDetailInfo(selfInfo.uid, false) @@ -233,7 +233,7 @@ export class NapCatOneBot11Adapter { ); } - private async reloadNetwork(prev: OneBotConfig, now: OneBotConfig): Promise { + private async reloadNetwork (prev: OneBotConfig, now: OneBotConfig): Promise { const prevLog = await this.creatOneBotLog(prev); const newLog = await this.creatOneBotLog(now); this.context.logger.log(`[Notice] [OneBot11] 配置变更前:\n${prevLog}`); @@ -279,7 +279,7 @@ export class NapCatOneBot11Adapter { } } - private initMsgListener() { + private initMsgListener () { const msgListener = new NodeIKernelMsgListener(); msgListener.onRecvSysMsg = (msg) => { this.apis.MsgApi.parseSysMessage(msg) @@ -392,7 +392,7 @@ export class NapCatOneBot11Adapter { this.context.session.getMsgService().addKernelMsgListener(proxiedListenerOf(msgListener, this.context.logger)); } - private initBuddyListener() { + private initBuddyListener () { const buddyListener = new NodeIKernelBuddyListener(); buddyListener.onBuddyReqChange = async (reqs) => { @@ -423,7 +423,7 @@ export class NapCatOneBot11Adapter { .addKernelBuddyListener(proxiedListenerOf(buddyListener, this.context.logger)); } - private initGroupListener() { + private initGroupListener () { const groupListener = new NodeIKernelGroupListener(); groupListener.onGroupNotifiesUpdated = async (_, notifies) => { @@ -516,7 +516,7 @@ export class NapCatOneBot11Adapter { .addKernelGroupListener(proxiedListenerOf(groupListener, this.context.logger)); } - private async emitMsg(message: RawMessage) { + private async emitMsg (message: RawMessage) { const network = await this.networkManager.getAllConfig(); this.context.logger.logDebug('收到新消息 RawMessage', message); await Promise.allSettled([ @@ -525,7 +525,7 @@ export class NapCatOneBot11Adapter { ]); } - private async handleMsg(message: RawMessage, network: Array) { + private async handleMsg (message: RawMessage, network: Array) { // 过滤无效消息 if (message.msgType === NTMsgType.KMSGTYPENULL) { return; @@ -545,7 +545,7 @@ export class NapCatOneBot11Adapter { } } - private isSelfMessage(ob11Msg: { + private isSelfMessage (ob11Msg: { stringMsg: OB11Message; arrayMsg: OB11Message; }): boolean { @@ -553,7 +553,7 @@ export class NapCatOneBot11Adapter { ob11Msg.arrayMsg.user_id.toString() === this.core.selfInfo.uin; } - private createMsgMap(network: Array, ob11Msg: { + private createMsgMap (network: Array, ob11Msg: { stringMsg: OB11Message; arrayMsg: OB11Message; }, isSelfMsg: boolean, message: RawMessage): Map { @@ -572,7 +572,7 @@ export class NapCatOneBot11Adapter { return msgMap; } - private handleDebugNetwork(network: Array, msgMap: Map, message: RawMessage) { + private handleDebugNetwork (network: Array, msgMap: Map, message: RawMessage) { const debugNetwork = network.filter(e => e.enable && e.debug); if (debugNetwork.length > 0) { debugNetwork.forEach(adapter => { @@ -586,7 +586,7 @@ export class NapCatOneBot11Adapter { } } - private handleNotReportSelfNetwork(network: Array, msgMap: Map, isSelfMsg: boolean) { + private handleNotReportSelfNetwork (network: Array, msgMap: Map, isSelfMsg: boolean) { if (isSelfMsg) { const notReportSelfNetwork = network.filter(e => e.enable && (('reportSelfMessage' in e && !e.reportSelfMessage) || !('reportSelfMessage' in e))); notReportSelfNetwork.forEach(adapter => { @@ -595,7 +595,7 @@ export class NapCatOneBot11Adapter { } } - private async handleGroupEvent(message: RawMessage) { + private async handleGroupEvent (message: RawMessage) { try { // 群名片修改事件解析 任何都该判断 if (message.senderUin && message.senderUin !== '0') { @@ -628,7 +628,7 @@ export class NapCatOneBot11Adapter { } } - private async handlePrivateMsgEvent(message: RawMessage) { + private async handlePrivateMsgEvent (message: RawMessage) { try { if (message.msgType === NTMsgType.KMSGTYPEGRAYTIPS) { // 灰条为单元素消息 @@ -645,7 +645,7 @@ export class NapCatOneBot11Adapter { } } - private async emitRecallMsg(message: RawMessage, element: MessageElement) { + private async emitRecallMsg (message: RawMessage, element: MessageElement) { const peer: Peer = { chatType: message.chatType, peerUid: message.peerUid, guildId: '' }; const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId) ?? MessageUnique.createUniqueMsgId(peer, message.msgId); if (message.chatType === ChatType.KCHATTYPEC2C) { @@ -656,7 +656,7 @@ export class NapCatOneBot11Adapter { return undefined; } - private async emitFriendRecallMsg(message: RawMessage, oriMessageId: number, element: MessageElement) { + private async emitFriendRecallMsg (message: RawMessage, oriMessageId: number, element: MessageElement) { const operatorUid = element.grayTipElement?.revokeElement.operatorUid; if (!operatorUid) return undefined; return new OB11FriendRecallNoticeEvent( @@ -666,7 +666,7 @@ export class NapCatOneBot11Adapter { ); } - private async emitGroupRecallMsg(message: RawMessage, oriMessageId: number, element: MessageElement) { + private async emitGroupRecallMsg (message: RawMessage, oriMessageId: number, element: MessageElement) { const operatorUid = element.grayTipElement?.revokeElement.operatorUid; if (!operatorUid) return undefined; const operatorId = await this.core.apis.UserApi.getUinByUidV2(operatorUid); diff --git a/packages/napcat-protobuf/NapProto.ts b/packages/napcat-protobuf/NapProto.ts index ecf842ad..d9b5c288 100644 --- a/packages/napcat-protobuf/NapProto.ts +++ b/packages/napcat-protobuf/NapProto.ts @@ -7,18 +7,18 @@ type LowerCamelCase = CamelCaseHelper; type CamelCaseHelper< S extends string, CapNext extends boolean, - IsFirstChar extends boolean, + IsFirstChar extends boolean > = S extends `${infer F}${infer R}` - ? F extends '_' - ? CamelCaseHelper - : F extends `${number}` - ? `${F}${CamelCaseHelper}` - : CapNext extends true - ? `${Uppercase}${CamelCaseHelper}` - : IsFirstChar extends true - ? `${Lowercase}${CamelCaseHelper}` - : `${F}${CamelCaseHelper}` - : ''; + ? F extends '_' + ? CamelCaseHelper + : F extends `${number}` + ? `${F}${CamelCaseHelper}` + : CapNext extends true + ? `${Uppercase}${CamelCaseHelper}` + : IsFirstChar extends true + ? `${Lowercase}${CamelCaseHelper}` + : `${F}${CamelCaseHelper}` + : ''; type ScalarTypeToTsType = T extends | ScalarType.DOUBLE @@ -28,36 +28,36 @@ type ScalarTypeToTsType = T extends | ScalarType.UINT32 | ScalarType.SFIXED32 | ScalarType.SINT32 - ? number - : T extends ScalarType.INT64 | ScalarType.UINT64 | ScalarType.FIXED64 | ScalarType.SFIXED64 | ScalarType.SINT64 - ? bigint - : T extends ScalarType.BOOL - ? boolean - : T extends ScalarType.STRING - ? string - : T extends ScalarType.BYTES - ? Uint8Array - : never; + ? number + : T extends ScalarType.INT64 | ScalarType.UINT64 | ScalarType.FIXED64 | ScalarType.SFIXED64 | ScalarType.SINT64 + ? bigint + : T extends ScalarType.BOOL + ? boolean + : T extends ScalarType.STRING + ? string + : T extends ScalarType.BYTES + ? Uint8Array + : never; interface BaseProtoFieldType { - kind: 'scalar' | 'message'; - no: number; - type: T; - optional: O; - repeat: R; + kind: 'scalar' | 'message'; + no: number; + type: T; + optional: O; + repeat: R; } export interface ScalarProtoFieldType - extends BaseProtoFieldType { - kind: 'scalar'; + extends BaseProtoFieldType { + kind: 'scalar'; } export interface MessageProtoFieldType< T extends () => ProtoMessageType, O extends boolean, - R extends O extends true ? false : boolean, + R extends O extends true ? false : boolean > extends BaseProtoFieldType { - kind: 'message'; + kind: 'message'; } type ProtoFieldType = @@ -65,62 +65,62 @@ type ProtoFieldType = | MessageProtoFieldType<() => ProtoMessageType, boolean, boolean>; type ProtoMessageType = { - [key: string]: ProtoFieldType; + [key: string]: ProtoFieldType; }; export function ProtoField< T extends ScalarType, O extends boolean = false, - R extends O extends true ? false : boolean = false, ->(no: number, type: T, optional?: O, repeat?: R): ScalarProtoFieldType; + R extends O extends true ? false : boolean = false +> (no: number, type: T, optional?: O, repeat?: R): ScalarProtoFieldType; export function ProtoField< T extends () => ProtoMessageType, O extends boolean = false, - R extends O extends true ? false : boolean = false, ->(no: number, type: T, optional?: O, repeat?: R): MessageProtoFieldType; -export function ProtoField( - no: number, - type: ScalarType | (() => ProtoMessageType), - optional?: boolean, - repeat?: boolean + R extends O extends true ? false : boolean = false +> (no: number, type: T, optional?: O, repeat?: R): MessageProtoFieldType; +export function ProtoField ( + no: number, + type: ScalarType | (() => ProtoMessageType), + optional?: boolean, + repeat?: boolean ): ProtoFieldType { - if (typeof type === 'function') { - return { kind: 'message', no: no, type: type, optional: optional ?? false, repeat: repeat ?? false }; - } else { - return { kind: 'scalar', no: no, type: type, optional: optional ?? false, repeat: repeat ?? false }; - } + if (typeof type === 'function') { + return { kind: 'message', no, type, optional: optional ?? false, repeat: repeat ?? false }; + } else { + return { kind: 'scalar', no, type, optional: optional ?? false, repeat: repeat ?? false }; + } } type ProtoFieldReturnType = - NonNullable extends ScalarProtoFieldType - ? ScalarTypeToTsType - : T extends NonNullable> - ? NonNullable, E>> - : never; + NonNullable extends ScalarProtoFieldType + ? ScalarTypeToTsType + : T extends NonNullable> + ? NonNullable, E>> + : never; type RequiredFieldsBaseType = { - [K in keyof T as T[K] extends { optional: true } ? never : LowerCamelCase]: T[K] extends { - repeat: true; - } - ? ProtoFieldReturnType[] - : ProtoFieldReturnType; + [K in keyof T as T[K] extends { optional: true } ? never : LowerCamelCase]: T[K] extends { + repeat: true; + } + ? ProtoFieldReturnType[] + : ProtoFieldReturnType; }; type OptionalFieldsBaseType = { - [K in keyof T as T[K] extends { optional: true } ? LowerCamelCase : never]?: T[K] extends { - repeat: true; - } - ? ProtoFieldReturnType[] - : ProtoFieldReturnType; + [K in keyof T as T[K] extends { optional: true } ? LowerCamelCase : never]?: T[K] extends { + repeat: true; + } + ? ProtoFieldReturnType[] + : ProtoFieldReturnType; }; type RequiredFieldsType = E extends true - ? Partial> - : RequiredFieldsBaseType; + ? Partial> + : RequiredFieldsBaseType; type OptionalFieldsType = E extends true - ? Partial> - : OptionalFieldsBaseType; + ? Partial> + : OptionalFieldsBaseType; type NapProtoStructType = RequiredFieldsType & OptionalFieldsType; @@ -129,72 +129,74 @@ export type NapProtoEncodeStructType = NapProtoStructType; export type NapProtoDecodeStructType = NapProtoStructType; class NapProtoRealMsg { - private readonly _field: PartialFieldInfo[]; - private readonly _proto_msg: MessageType>; - private static cache = new WeakMap>(); + private readonly _field: PartialFieldInfo[]; + private readonly _proto_msg: MessageType>; + private static cache = new WeakMap>(); - private constructor(fields: T) { - this._field = Object.keys(fields).map((key) => { - const field = fields[key]; - if (field.kind === 'scalar') { - const repeatType = field.repeat - ? [ScalarType.STRING, ScalarType.BYTES].includes(field.type) - ? RepeatType.UNPACKED - : RepeatType.PACKED - : RepeatType.NO; - return { - no: field.no, - name: key, - kind: 'scalar', - T: field.type, - opt: field.optional, - repeat: repeatType, - }; - } else if (field.kind === 'message') { - return { - no: field.no, - name: key, - kind: 'message', - repeat: field.repeat ? RepeatType.PACKED : RepeatType.NO, - T: () => NapProtoRealMsg.getInstance(field.type())._proto_msg, - }; - } - }) as PartialFieldInfo[]; - this._proto_msg = new MessageType>('nya', this._field); - } + private constructor (fields: T) { + this._field = Object.keys(fields).map((key) => { + const field = fields[key]; + if (field.kind === 'scalar') { + const repeatType = field.repeat + ? [ScalarType.STRING, ScalarType.BYTES].includes(field.type) + ? RepeatType.UNPACKED + : RepeatType.PACKED + : RepeatType.NO; + return { + no: field.no, + name: key, + kind: 'scalar', + T: field.type, + opt: field.optional, + repeat: repeatType, + }; + } else if (field.kind === 'message') { + return { + no: field.no, + name: key, + kind: 'message', + repeat: field.repeat ? RepeatType.PACKED : RepeatType.NO, + T: () => NapProtoRealMsg.getInstance(field.type())._proto_msg, + }; + } else { + throw new Error(`Unknown field kind: ${field.kind}`); + } + }) as PartialFieldInfo[]; + this._proto_msg = new MessageType>('nya', this._field); + } - static getInstance(fields: T): NapProtoRealMsg { - let instance = this.cache.get(fields); - if (!instance) { - instance = new NapProtoRealMsg(fields); - this.cache.set(fields, instance); - } - return instance; + static getInstance(fields: T): NapProtoRealMsg { + let instance = this.cache.get(fields); + if (!instance) { + instance = new NapProtoRealMsg(fields); + this.cache.set(fields, instance); } + return instance; + } - encode(data: NapProtoEncodeStructType): Uint8Array { - return this._proto_msg.toBinary(this._proto_msg.create(data as PartialMessage>)); - } + encode (data: NapProtoEncodeStructType): Uint8Array { + return this._proto_msg.toBinary(this._proto_msg.create(data as PartialMessage>)); + } - decode(data: Uint8Array): NapProtoDecodeStructType { - return this._proto_msg.fromBinary(data) as NapProtoDecodeStructType; - } + decode (data: Uint8Array): NapProtoDecodeStructType { + return this._proto_msg.fromBinary(data) as NapProtoDecodeStructType; + } } export class NapProtoMsg { - private realMsg: NapProtoRealMsg; + private realMsg: NapProtoRealMsg; - constructor(fields: T) { - this.realMsg = NapProtoRealMsg.getInstance(fields); - } + constructor (fields: T) { + this.realMsg = NapProtoRealMsg.getInstance(fields); + } - encode(data: NapProtoEncodeStructType): Uint8Array { - return this.realMsg.encode(data); - } + encode (data: NapProtoEncodeStructType): Uint8Array { + return this.realMsg.encode(data); + } - decode(data: Uint8Array): NapProtoDecodeStructType { - return this.realMsg.decode(data); - } + decode (data: Uint8Array): NapProtoDecodeStructType { + return this.realMsg.decode(data); + } } export { ScalarType } from '@protobuf-ts/runtime'; diff --git a/packages/napcat-shell-loader/loadNapCat.js b/packages/napcat-shell-loader/loadNapCat.js index 81af5e6e..25e1ed19 100644 --- a/packages/napcat-shell-loader/loadNapCat.js +++ b/packages/napcat-shell-loader/loadNapCat.js @@ -1,5 +1,5 @@ const path = require('path'); const CurrentPath = path.dirname(__filename); (async () => { - await import("file://" + path.join(CurrentPath, './napcat/napcat.mjs')); -})(); \ No newline at end of file + await import('file://' + path.join(CurrentPath, './napcat/napcat.mjs')); +})(); diff --git a/packages/napcat-shell/base.ts b/packages/napcat-shell/base.ts index 69f8046e..cba8eb64 100644 --- a/packages/napcat-shell/base.ts +++ b/packages/napcat-shell/base.ts @@ -364,7 +364,7 @@ export async function NCoreInitShell () { await initializeLoginService(loginService, basicInfoWrapper, dataPathGlobal, systemVersion, hostname); handleProxy(session, logger); - let quickLoginUin: string | undefined = undefined; + let quickLoginUin: string | undefined; try { const args = process.argv; const qIndex = args.findIndex(arg => arg === '-q' || arg === '--qq'); diff --git a/packages/napcat-shell/vite.config.ts b/packages/napcat-shell/vite.config.ts index 790ff370..5b4f74c1 100644 --- a/packages/napcat-shell/vite.config.ts +++ b/packages/napcat-shell/vite.config.ts @@ -3,15 +3,15 @@ import { defineConfig, PluginOption, UserConfig } from 'vite'; import path, { resolve } from 'path'; import nodeResolve from '@rollup/plugin-node-resolve'; import { builtinModules } from 'module'; -import napcatVersion from "napcat-vite/vite-plugin-version.js"; -import { autoIncludeTSPlugin } from "napcat-vite/vite-auto-include.js"; +import napcatVersion from 'napcat-vite/vite-plugin-version.js'; +import { autoIncludeTSPlugin } from 'napcat-vite/vite-auto-include.js'; import react from '@vitejs/plugin-react-swc'; -//依赖排除 +// 依赖排除 const external = [ 'silk-wasm', 'ws', - 'express' + 'express', ]; const nodeModules = [...builtinModules, builtinModules.map((m) => `node:${m}`)].flat(); @@ -20,8 +20,8 @@ const ShellBaseConfigPlugin: PluginOption[] = [ autoIncludeTSPlugin({ entries: [ { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-core/protocol') }, - { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') } - ] + { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') }, + ], }), cp({ targets: [ @@ -29,7 +29,7 @@ const ShellBaseConfigPlugin: PluginOption[] = [ { src: '../napcat-webui-frontend/dist/', dest: 'dist/static/', flatten: false }, { src: '../napcat-core/external/napcat.json', dest: 'dist/config/' }, { src: '../../package.json', dest: 'dist' }, - { src: '../napcat-shell-loader', dest: 'dist' } + { src: '../napcat-shell-loader', dest: 'dist' }, ], }), nodeResolve(), @@ -62,7 +62,7 @@ const ShellBaseConfig = (source_map: boolean = false) => fileName: (_, entryName) => `${entryName}.mjs`, }, rollupOptions: { - external: [...nodeModules, ...external] + external: [...nodeModules, ...external], }, }, }); diff --git a/packages/napcat-test/sha1Stream.test.ts b/packages/napcat-test/sha1Stream.test.ts index bf9600eb..94940aa5 100644 --- a/packages/napcat-test/sha1Stream.test.ts +++ b/packages/napcat-test/sha1Stream.test.ts @@ -84,4 +84,4 @@ describe('Sha1Stream', () => { expect(hash).toEqual(expectedDigest); } }); -}); \ No newline at end of file +}); diff --git a/packages/napcat-test/vitest.config.ts b/packages/napcat-test/vitest.config.ts index 04c89db4..2ec5edf6 100644 --- a/packages/napcat-test/vitest.config.ts +++ b/packages/napcat-test/vitest.config.ts @@ -11,4 +11,4 @@ export default defineConfig({ '@': resolve(__dirname, '../../'), }, }, -}); \ No newline at end of file +}); diff --git a/packages/napcat-vite/vite-auto-include.js b/packages/napcat-vite/vite-auto-include.js index 20c91129..ba8fa9ff 100644 --- a/packages/napcat-vite/vite-auto-include.js +++ b/packages/napcat-vite/vite-auto-include.js @@ -1,78 +1,78 @@ import path from 'path'; import fs from 'fs'; -export function autoIncludeTSPlugin(options) { - // options: { entries: [{ entry: 'napcat.ts', dir: './utils' }, ...] } - const { entries } = options; - let tsFilesMap = {}; +export function autoIncludeTSPlugin (options) { + // options: { entries: [{ entry: 'napcat.ts', dir: './utils' }, ...] } + const { entries } = options; + let tsFilesMap = {}; - return { - name: 'vite-auto-include', + return { + name: 'vite-auto-include', - async buildStart() { - tsFilesMap = {}; - for (const { entry, dir } of entries) { - if (!tsFilesMap[entry]) { - tsFilesMap[entry] = []; - } - const fullDir = path.resolve(dir); - const allTsFiles = await findTSFiles(fullDir); + async buildStart () { + tsFilesMap = {}; + for (const { entry, dir } of entries) { + if (!tsFilesMap[entry]) { + tsFilesMap[entry] = []; + } + const fullDir = path.resolve(dir); + const allTsFiles = await findTSFiles(fullDir); - const validFiles = []; - allTsFiles.forEach((filePath) => { - try { - const source = fs.readFileSync(filePath, 'utf-8'); - if (source && source.trim() !== '') { - validFiles.push(filePath); - } else { - // Skipping empty file: ${filePath} - } - } catch (error) { - console.error(`Error reading file: ${filePath}`, error); - } - }); - - tsFilesMap[entry].push(...validFiles); + const validFiles = []; + allTsFiles.forEach((filePath) => { + try { + const source = fs.readFileSync(filePath, 'utf-8'); + if (source && source.trim() !== '') { + validFiles.push(filePath); + } else { + // Skipping empty file: ${filePath} } - }, + } catch (error) { + console.error(`Error reading file: ${filePath}`, error); + } + }); - transform(code, id) { - for (const [entry, tsFiles] of Object.entries(tsFilesMap)) { - const isMatch = id.endsWith(entry) || id.includes(entry); - if (isMatch && tsFiles.length > 0) { - const imports = tsFiles.map(filePath => { - const relativePath = path.relative(path.dirname(id), filePath).replace(/\\/g, '/'); - return `import './${relativePath}';`; - }).join('\n'); + tsFilesMap[entry].push(...validFiles); + } + }, - const transformedCode = imports + '\n' + code; + transform (code, id) { + for (const [entry, tsFiles] of Object.entries(tsFilesMap)) { + const isMatch = id.endsWith(entry) || id.includes(entry); + if (isMatch && tsFiles.length > 0) { + const imports = tsFiles.map(filePath => { + const relativePath = path.relative(path.dirname(id), filePath).replace(/\\/g, '/'); + return `import './${relativePath}';`; + }).join('\n'); - return { - code: transformedCode, - map: { mappings: '' } // 空映射即可,VSCode 可以在 TS 上断点 - }; - } - } + const transformedCode = imports + '\n' + code; - return null; - }, + return { + code: transformedCode, + map: { mappings: '' }, // 空映射即可,VSCode 可以在 TS 上断点 + }; + } + } - }; + return null; + }, + + }; } // 辅助函数:查找所有 .ts 文件 -async function findTSFiles(dir) { - const files = []; - const items = await fs.promises.readdir(dir, { withFileTypes: true }); +async function findTSFiles (dir) { + const files = []; + const items = await fs.promises.readdir(dir, { withFileTypes: true }); - for (let item of items) { - const fullPath = path.join(dir, item.name); - if (item.isDirectory()) { - files.push(...await findTSFiles(fullPath)); // 递归查找子目录 - } else if (item.isFile() && fullPath.endsWith('.ts')) { - files.push(fullPath); // 收集 .ts 文件 - } + for (const item of items) { + const fullPath = path.join(dir, item.name); + if (item.isDirectory()) { + files.push(...await findTSFiles(fullPath)); // 递归查找子目录 + } else if (item.isFile() && fullPath.endsWith('.ts')) { + files.push(fullPath); // 收集 .ts 文件 } + } - return files; + return files; } diff --git a/packages/napcat-vite/vite-plugin-version.js b/packages/napcat-vite/vite-plugin-version.js index 9bcea274..3b508c53 100644 --- a/packages/napcat-vite/vite-plugin-version.js +++ b/packages/napcat-vite/vite-plugin-version.js @@ -1,7 +1,7 @@ -import fs from "fs"; -import path from "path"; -import https from "https"; -import { fileURLToPath } from "url"; +import fs from 'fs'; +import path from 'path'; +import https from 'https'; +import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -9,28 +9,28 @@ const __dirname = path.dirname(__filename); /** * NapCat Vite Plugin: fetches latest GitHub tag (not release) and injects into import.meta.env */ -export default function vitePluginNapcatVersion() { - const pluginDir = path.resolve(__dirname, "dist"); - const cacheFile = path.join(pluginDir, ".napcat-version.json"); - const owner = "NapNeko"; - const repo = "NapCatQQ"; +export default function vitePluginNapcatVersion () { + const pluginDir = path.resolve(__dirname, 'dist'); + const cacheFile = path.join(pluginDir, '.napcat-version.json'); + const owner = 'NapNeko'; + const repo = 'NapCatQQ'; const maxAgeMs = 24 * 60 * 60 * 1000; // cache 1 day const githubToken = process.env.GITHUB_TOKEN; fs.mkdirSync(pluginDir, { recursive: true }); - function readCache() { + function readCache () { try { const stat = fs.statSync(cacheFile); if (Date.now() - stat.mtimeMs < maxAgeMs) { - const data = JSON.parse(fs.readFileSync(cacheFile, "utf8")); + const data = JSON.parse(fs.readFileSync(cacheFile, 'utf8')); if (data?.tag) return data.tag; } } catch {} return null; } - function writeCache(tag) { + function writeCache (tag) { try { fs.writeFileSync( cacheFile, @@ -39,38 +39,38 @@ export default function vitePluginNapcatVersion() { } catch {} } - async function fetchLatestTag() { + async function fetchLatestTag () { const url = `https://api.github.com/repos/${owner}/${repo}/tags`; return new Promise((resolve, reject) => { const req = https.get( url, { headers: { - "User-Agent": "vite-plugin-napcat-version", - Accept: "application/vnd.github.v3+json", + 'User-Agent': 'vite-plugin-napcat-version', + Accept: 'application/vnd.github.v3+json', ...(githubToken ? { Authorization: `token ${githubToken}` } : {}), }, }, (res) => { - let data = ""; - res.on("data", (c) => (data += c)); - res.on("end", () => { + let data = ''; + res.on('data', (c) => (data += c)); + res.on('end', () => { try { const json = JSON.parse(data); if (Array.isArray(json) && json[0]?.name) { resolve(json[0].name); - } else reject(new Error("Invalid GitHub tag response")); + } else reject(new Error('Invalid GitHub tag response')); } catch (e) { reject(e); } }); } ); - req.on("error", reject); + req.on('error', reject); }); } - async function getVersion() { + async function getVersion () { const cached = readCache(); if (cached) return cached; try { @@ -78,37 +78,37 @@ export default function vitePluginNapcatVersion() { writeCache(tag); return tag; } catch (e) { - console.warn("[vite-plugin-napcat-version] Failed to fetch tag:", e.message); - return cached ?? "v0.0.0"; + console.warn('[vite-plugin-napcat-version] Failed to fetch tag:', e.message); + return cached ?? 'v0.0.0'; } } let lastTag = null; return { - name: "vite-plugin-napcat-version", - enforce: "pre", + name: 'vite-plugin-napcat-version', + enforce: 'pre', - async config(userConfig) { + async config (userConfig) { const tag = await getVersion(); console.log(`[vite-plugin-napcat-version] Using version: ${tag}`); lastTag = tag; return { define: { ...(userConfig.define || {}), - "import.meta.env.VITE_NAPCAT_VERSION": JSON.stringify(tag), + 'import.meta.env.VITE_NAPCAT_VERSION': JSON.stringify(tag), }, }; }, - handleHotUpdate(ctx) { + handleHotUpdate (ctx) { if (path.resolve(ctx.file) === cacheFile) { try { - const json = JSON.parse(fs.readFileSync(cacheFile, "utf8")); + const json = JSON.parse(fs.readFileSync(cacheFile, 'utf8')); const tag = json?.tag; if (tag && tag !== lastTag) { lastTag = tag; - ctx.server?.ws.send({ type: "full-reload" }); + ctx.server?.ws.send({ type: 'full-reload' }); } } catch {} } diff --git a/packages/napcat-webui-backend/src/helper/config.ts b/packages/napcat-webui-backend/src/helper/config.ts index ef0b0d1d..527a1671 100644 --- a/packages/napcat-webui-backend/src/helper/config.ts +++ b/packages/napcat-webui-backend/src/helper/config.ts @@ -1,4 +1,4 @@ -import { webUiPathWrapper, getInitialWebUiToken } from '@/napcat-webui-backend/index' +import { webUiPathWrapper, getInitialWebUiToken } from '@/napcat-webui-backend/index'; import { Type, Static } from '@sinclair/typebox'; import Ajv from 'ajv'; import fs, { constants } from 'node:fs/promises'; diff --git a/packages/napcat-webui-frontend/eslint.config.mjs b/packages/napcat-webui-frontend/eslint.config.mjs deleted file mode 100644 index ecbdd00f..00000000 --- a/packages/napcat-webui-frontend/eslint.config.mjs +++ /dev/null @@ -1,2 +0,0 @@ -import eslintConfig from '../eslint.config.mjs'; -export default eslintConfig; diff --git a/packages/napcat-webui-frontend/postcss.config.js b/packages/napcat-webui-frontend/postcss.config.js index 2b75bd8a..2aa7205d 100644 --- a/packages/napcat-webui-frontend/postcss.config.js +++ b/packages/napcat-webui-frontend/postcss.config.js @@ -1,6 +1,6 @@ export default { plugins: { tailwindcss: {}, - autoprefixer: {} - } -} + autoprefixer: {}, + }, +}; diff --git a/packages/napcat-webui-frontend/src/types/react-color.d.ts b/packages/napcat-webui-frontend/src/types/react-color.d.ts index a7c2e3c5..23056396 100644 --- a/packages/napcat-webui-frontend/src/types/react-color.d.ts +++ b/packages/napcat-webui-frontend/src/types/react-color.d.ts @@ -23,6 +23,6 @@ declare module 'react-color' { export const CirclePicker: any; export default { - SketchPicker: SketchPicker, + SketchPicker, } as any; } diff --git a/packages/napcat-webui-frontend/tailwind.config.js b/packages/napcat-webui-frontend/tailwind.config.js index 379ed05b..e48e7d97 100644 --- a/packages/napcat-webui-frontend/tailwind.config.js +++ b/packages/napcat-webui-frontend/tailwind.config.js @@ -1,4 +1,4 @@ -import { heroui } from '@heroui/theme' +import { heroui } from '@heroui/theme'; /** @type {import('tailwindcss').Config} */ export default { @@ -7,16 +7,16 @@ export default { './src/layouts/**/*.{js,ts,jsx,tsx,mdx}', './src/pages/**/*.{js,ts,jsx,tsx,mdx}', './src/components/**/*.{js,ts,jsx,tsx,mdx}', - './node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}' + './node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}', ], safelist: [ { pattern: - /bg-(primary|secondary|success|danger|warning|default)-(50|100|200|300|400|500|600|700|800|900)/ - } + /bg-(primary|secondary|success|danger|warning|default)-(50|100|200|300|400|500|600|700|800|900)/, + }, ], theme: { - extend: {} + extend: {}, }, darkMode: 'class', plugins: [ @@ -36,7 +36,7 @@ export default { 600: '#c20e4d', 700: '#920b3a', 800: '#610726', - 900: '#310413' + 900: '#310413', }, danger: { DEFAULT: '#DB3694', @@ -50,9 +50,9 @@ export default { 600: '#BC278B', 700: '#9D1B7F', 800: '#7F1170', - 900: '#690A66' - } - } + 900: '#690A66', + }, + }, }, dark: { colors: { @@ -68,7 +68,7 @@ export default { 600: '#f871a0', 700: '#faa0bf', 800: '#fdd0df', - 900: '#fee7ef' + 900: '#fee7ef', }, danger: { DEFAULT: '#DB3694', @@ -82,11 +82,11 @@ export default { 600: '#F485AE', 700: '#FBAFC4', 800: '#FDD7DD', - 900: '#FEEAF6' - } - } - } - } - }) - ] -} + 900: '#FEEAF6', + }, + }, + }, + }, + }), + ], +}; diff --git a/packages/napcat-webui-frontend/vite.config.ts b/packages/napcat-webui-frontend/vite.config.ts index d9cf306c..f7087409 100644 --- a/packages/napcat-webui-frontend/vite.config.ts +++ b/packages/napcat-webui-frontend/vite.config.ts @@ -1,18 +1,18 @@ -import react from '@vitejs/plugin-react' -import path from 'node:path' -import { defineConfig, loadEnv, normalizePath } from 'vite' -import { viteStaticCopy } from 'vite-plugin-static-copy' -import tsconfigPaths from 'vite-tsconfig-paths' +import react from '@vitejs/plugin-react'; +import path from 'node:path'; +import { defineConfig, loadEnv, normalizePath } from 'vite'; +import { viteStaticCopy } from 'vite-plugin-static-copy'; +import tsconfigPaths from 'vite-tsconfig-paths'; const monacoEditorPath = normalizePath( path.resolve(__dirname, 'node_modules/monaco-editor/min/vs') -) +); // https://vitejs.dev/config/ export default defineConfig(({ mode }) => { - const env = loadEnv(mode, process.cwd()) - const backendDebugUrl = env.VITE_DEBUG_BACKEND_URL - console.log('backendDebugUrl', backendDebugUrl) + const env = loadEnv(mode, process.cwd()); + const backendDebugUrl = env.VITE_DEBUG_BACKEND_URL; + console.log('backendDebugUrl', backendDebugUrl); return { plugins: [ react(), @@ -21,10 +21,10 @@ export default defineConfig(({ mode }) => { targets: [ { src: monacoEditorPath, - dest: 'monaco-editor/min' - } - ] - }) + dest: 'monaco-editor/min', + }, + ], + }), ], base: '/webui/', server: { @@ -32,11 +32,11 @@ export default defineConfig(({ mode }) => { '/api/ws/terminal': { target: backendDebugUrl, ws: true, - changeOrigin: true + changeOrigin: true, }, '/api': backendDebugUrl, - '/files': backendDebugUrl - } + '/files': backendDebugUrl, + }, }, build: { assetsInlineLimit: 0, @@ -49,10 +49,10 @@ export default defineConfig(({ mode }) => { 'react-hook-form': ['react-hook-form'], 'react-icons': ['react-icons'], 'react-hot-toast': ['react-hot-toast'], - qface: ['qface'] - } - } - } - } - } -}) + qface: ['qface'], + }, + }, + }, + }, + }; +}); diff --git a/vitest.config.ts b/vitest.config.ts index d771157a..cd3d1592 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -12,4 +12,4 @@ export default defineConfig({ '@': resolve(__dirname, 'packages'), }, }, -}); \ No newline at end of file +});