SnowCat 雪猫底层全源码:NapCat 4.18.28 底座 + SnowLuma 能力移植 + V8 通道适配 9.9.37

26 包 monorepo(TS 全源码):
- snowcat-core: NT 内核 API 封装 + listener(含 9.9.37 六回调适配)+ Packet 发包
- snowcat-onebot: OneBot v11 全动作 + MCP Streamable HTTP 适配器 + 稳定线
- snowcat-webui-frontend/backend: 雪猫控制台(React+HeroUI)
- snowcat-shell: 单文件 bundle 出口(vite inlineDynamicImports)
- snowcat-native: napi2native / MoeHoo / ffmpeg / pty 运行时
- 56 项 SnowLuma 独门动作移植(qzone 全家桶/群相册/装扮/闪照/收藏)
- 工具件: 解包器/启动器/便携制作器/doctor

GitHub 关联已全量指向 DandanLLab/SnowCatQQ
This commit is contained in:
天天的鸟蛋蛋 committed 2026-11-12 06:27:36 +08:00
commit b9655a5ab1
1048 files changed
+130851

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
# NapCat-Types
NapCat 类型定义包,包含 NapCat 及其插件开发所需的所有类型定义。
+104
View File
@@ -0,0 +1,104 @@
// 外部模块 shim,提供最小的可运行值和类型,避免类型包依赖外部环境
// node:* 模块移除 mock,使用系统自带类型
// (ws/express/winston) now provided by real type deps (@types/ws, @types/express, winston)
declare module 'ffmpeg-static' {
const _ffmpeg_static_default: any;
export default _ffmpeg_static_default;
}
declare module 'fluent-ffmpeg' {
const _fluent_ffmpeg_default: any;
export default _fluent_ffmpeg_default;
}
declare module 'sharp' {
const _sharp_default: any;
export default _sharp_default;
}
declare module 'uuid' {
export function v4 (...args: any[]): string;
}
declare module 'axios' {
const _axios_default: any;
export default _axios_default;
}
declare module 'body-parser' {
const _body_parser_default: any;
export default _body_parser_default;
}
declare module 'cors' {
const _cors_default: any;
export default _cors_default;
}
declare module 'file-type' {
export function fileTypeFromFile (path: string): Promise<any>;
}
declare module 'image-size' {
const _image_size_default: any;
export default _image_size_default;
}
declare module 'jimp' {
const _jimp_default: any;
export default _jimp_default;
}
declare module 'qrcode' {
const _qrcode_default: any;
export default _qrcode_default;
}
declare module 'yaml' {
export const parse: (...args: any[]) => any;
export const stringify: (...args: any[]) => any;
}
declare module 'snowcat-protobuf' {
export class NapProtoMsg<T = any> {
constructor (schema: any);
decode (buffer: any): T;
encode (value: any): Uint8Array;
}
export function ProtoField (...args: any[]): any;
export type NapProtoEncodeStructType<_T> = any;
export type NapProtoDecodeStructType<_T> = any;
export type ScalarProtoFieldType<_T> = any;
export type MessageProtoFieldType<_T> = any;
export const ScalarType: {
STRING: any;
INT64: any;
INT32: any;
UINT32: any;
UINT64: any;
BYTES: any;
BOOL: any;
[key: string]: any;
};
}
declare module 'inversify' {
export class Container {
bind: (...args: any[]) => any;
get: <T = any>(id: any) => T;
}
export function injectable (...args: any[]): any;
export function inject (...args: any[]): any;
export interface ServiceIdentifier<_T = any> { }
const _inversify_default: any;
export default _inversify_default;
}
declare module 'ip' {
export function toBuffer (ip: any, buffer?: Buffer, offset?: number): Buffer;
export function toString (buffer: any, offset?: number, length?: number): string;
const _ip_default: any;
export default _ip_default;
}
+8
View File
@@ -0,0 +1,8 @@
// 聚合导出核心库的所有内容(包括枚举、类和类型)
export * from '../snowcat-core/index';
// 聚合导出 OneBot 的所有内容
export * from '../snowcat-onebot/index';
// Ensure the shims file exists next to the emitted JS as well.
export type { };
+24
View File
@@ -0,0 +1,24 @@
{
"name": "snowcat-types",
"version": "0.0.1",
"private": false,
"type": "module",
"types": "./dist/snowcat-types/index.d.ts",
"files": [
"dist/**/*"
],
"scripts": {
"build": "tsc --project tsconfig.json && tsc-alias --project tsconfig.json --outDir dist && node ./scripts/post-build.mjs && node ./scripts/copy-dist.mjs",
"test": "pnpm -s exec tsc --project tsconfig.json --noEmit",
"publish": "cd dist && npm publish"
},
"dependencies": {
"@types/node": "^22.10.7",
"@sinclair/typebox": "^0.34.38"
},
"devDependencies": {
"snowcat-core": "workspace:*",
"snowcat-onebot": "workspace:*",
"tsc-alias": "^1.8.16"
}
}
@@ -0,0 +1,19 @@
{
"name": "snowcat-types",
"version": "0.0.17",
"private": false,
"type": "module",
"types": "./snowcat-types/index.d.ts",
"files": [
"./**/*"
],
"dependencies": {
"@types/node": "^22.10.7",
"@sinclair/typebox": "^0.34.38"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public",
"tag": "latest"
}
}
@@ -0,0 +1,13 @@
// 复制 cp README.md dist/ && cp package.public.json dist/package.json
import { copyFile } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = fileURLToPath(new URL('../', import.meta.url));
await copyFile(
join(__dirname, 'package.public.json'),
join(__dirname, 'dist', 'package.json')
);
await copyFile(
join(__dirname, 'README.md'),
join(__dirname, 'dist', 'README.md')
);
@@ -0,0 +1,118 @@
import { readdir, readFile, writeFile, rename } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = fileURLToPath(new URL('../', import.meta.url));
const distDir = join(__dirname, 'dist');
// 允许保留的包(白名单)
const ALLOWED_PACKAGES = [
'@sinclair/typebox',
'node:', // node: 前缀的内置模块
];
function isAllowedImport (importPath) {
return ALLOWED_PACKAGES.some(pkg => importPath.startsWith(pkg));
}
function removeExternalImports (content) {
const lines = content.split('\n');
const resultLines = [];
for (const line of lines) {
// 匹配 import 语句
const importMatch = line.match(/^import\s+.*\s+from\s+['"]([^'"]+)['"]/);
if (importMatch) {
const importPath = importMatch[1];
// 如果是相对路径或白名单包,保留
if (importPath.startsWith('.') || importPath.startsWith('/') || isAllowedImport(importPath)) {
resultLines.push(line);
}
// 否则移除该 import
continue;
}
resultLines.push(line);
}
return resultLines.join('\n');
}
function replaceExternalTypes (content) {
let result = content;
// 替换带泛型的类型(先处理复杂的)
result = result.replace(/NapProtoDecodeStructType<[^>]+>/g, 'any');
result = result.replace(/NapProtoEncodeStructType<[^>]+>/g, 'any');
result = result.replace(/ValidateFunction<[^>]+>/g, 'any');
// 替换 winston.Logger 等带命名空间的类型
result = result.replace(/winston\.Logger/g, 'any');
result = result.replace(/winston\.transport/g, 'any');
result = result.replace(/express\.Express/g, 'any');
result = result.replace(/express\.Application/g, 'any');
result = result.replace(/express\.Router/g, 'any');
// 替换独立的类型名(需要小心不要替换变量名)
// 使用类型上下文的模式匹配
const typeContextPatterns = [
// : Type
/:\s*(WebSocket|WebSocketServer|RawData|Container|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)(?=\s*[;,)\]}|&]|$)/g,
// <Type>
/<(WebSocket|WebSocketServer|RawData|Container|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)>/g,
// Type[]
/(WebSocket|WebSocketServer|RawData|Container|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)\[\]/g,
// extends Type
/extends\s+(WebSocket|WebSocketServer|RawData|Container|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)(?=\s*[{,])/g,
// implements Type
/implements\s+(WebSocket|WebSocketServer|RawData|Container|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)(?=\s*[{,])/g,
];
for (const pattern of typeContextPatterns) {
result = result.replace(pattern, (match, typeName) => {
return match.replace(typeName, 'any');
});
}
return result;
}
async function traverseDirectory (dir) {
const entries = await readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = join(dir, entry.name);
if (entry.isDirectory()) {
await traverseDirectory(fullPath);
} else if (entry.isFile() && entry.name.endsWith('.d.ts')) {
await processFile(fullPath);
}
}
}
async function processFile (filePath) {
// Read file content
let content = await readFile(filePath, 'utf-8');
// 1. 移除外部包的 import
content = removeExternalImports(content);
// 2. 替换外部类型为 any
content = replaceExternalTypes(content);
// 3. Replace "export declare enum" with "export enum"
content = content.replace(/export declare enum/g, 'export enum');
// Write back the modified content
await writeFile(filePath, content, 'utf-8');
// Rename .d.ts to .ts
const newPath = filePath.replace(/\.d\.ts$/, '.ts');
await rename(filePath, newPath);
// console.log(`Processed: ${basename(filePath)} -> ${basename(newPath)}`);
}
console.log('Starting post-build processing...');
await traverseDirectory(distDir);
console.log('Post-build processing completed!');
+36
View File
@@ -0,0 +1,36 @@
import {
ChatType,
ElementType,
SnowCatCore,
NTQQMsgApi,
NapCatOneBot11Adapter,
OB11Message,
OB11BaseMessageEvent,
OB11BaseMetaEvent,
} from './dist/snowcat-types/index';
console.log('--- SnowCat Comprehensive Type Test ---');
// 1. 测试枚举 (Core)
console.log('ChatType.KCHATTYPEGROUP:', ChatType.KCHATTYPEGROUP); // 应输出 2
console.log('ElementType.TEXT:', ElementType.TEXT); // 应输出 1
// 2. 测试类型 (Core)
const _coreStub = {} as SnowCatCore;
const _apiStub = {} as NTQQMsgApi;
console.log('Core types access check: OK');
// 3. 测试类和类型 (OneBot)
const _obAdapterStub = {} as NapCatOneBot11Adapter;
const _obMsgStub = {} as OB11Message;
const _baseMessageEventStub = {} as OB11BaseMessageEvent;
const _baseMetaEventStub = {} as OB11BaseMetaEvent;
console.log('OneBot types and events access check: OK');
// 4. 验证导出完整性
if (ChatType.KCHATTYPEGROUP === 2 && ElementType.TEXT === 1) {
console.log('\n✅ ALL TESTS PASSED: Types, Enums and Events are correctly exported and accessible.');
} else {
console.error('\n❌ TESTS FAILED: Enum value mismatch.');
throw new Error('Test Failed');
}
+20
View File
@@ -0,0 +1,20 @@
import { ChatType, ElementType, SnowCatCore, NTQQMsgApi } from './index';
console.log('--- SnowCat Types Manual Test ---');
// 测试枚举值 (snowcat-core enums)
console.log('ChatType.KCHATTYPEGROUP:', ChatType.KCHATTYPEGROUP);
console.log('ElementType.TEXT:', ElementType.TEXT);
// 测试 snowcat-core 的类型和类
const coreStub = {} as SnowCatCore;
const apiStub = {} as NTQQMsgApi;
console.log('SnowCatCore type check:', !!coreStub);
console.log('NTQQMsgApi type check:', !!apiStub);
if (ChatType.KCHATTYPEGROUP === 2 && ElementType.TEXT === 1) {
console.log('Test Passed: core enums and types are correctly exported.');
} else {
throw new Error('Test Failed: Enum values do not match expected values.');
}
+51
View File
@@ -0,0 +1,51 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "..",
"declaration": true,
"emitDeclarationOnly": true,
"skipLibCheck": true,
"stripInternal": true,
"noEmitOnError": false,
"paths": {
"snowcat-core": [
"../../packages/snowcat-core/index.ts"
],
"snowcat-onebot": [
"../../packages/snowcat-onebot/index.ts"
],
"snowcat-common/src/*": [
"../../packages/snowcat-common/src/*"
],
"snowcat-image-size/src/*": [
"../../packages/snowcat-image-size/src/*"
],
"@/snowcat-core/*": [
"../../packages/snowcat-core/*"
],
"@/snowcat-onebot/*": [
"../../packages/snowcat-onebot/*"
],
"@/snowcat-common/*": [
"../../packages/snowcat-common/*"
],
"@/snowcat-webui-backend/*": [
"../../packages/snowcat-webui-backend/*"
],
"@/*": [
"../../packages/*"
]
}
},
"include": [
"./index.ts",
"../snowcat-core/**/*.ts",
"../snowcat-onebot/**/*.ts",
"../snowcat-common/**/*.ts"
],
"exclude": [
"node_modules",
"dist"
]
}