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

+165
View File
@@ -0,0 +1,165 @@
import { describe, expect, test } from 'vitest';
import { TypeCompiler } from '@sinclair/typebox/compiler';
import { Value } from '@sinclair/typebox/value';
import { Type } from '@sinclair/typebox';
import { OB11MessageDataSchema, OB11MessageSchema, OB11PostSendMsgSchema } from '../snowcat-onebot/types/message';
import { OB11MessageSchema as OB11ActionMessageSchema } from '../snowcat-onebot/action/schemas';
import { OneBotConfigSchema, loadConfig as loadOneBotConfig, OneBotConfig } from '../snowcat-onebot/config';
import { SnowCatConfigSchema } from '../snowcat-core/helper/config';
describe('SnowCat Schemas Compilation', () => {
test('should compile OB11MessageDataSchema without duplicate id error', () => {
expect(() => TypeCompiler.Compile(OB11MessageDataSchema)).not.toThrow();
});
test('should compile OB11MessageSchema without duplicate id error', () => {
expect(() => TypeCompiler.Compile(OB11MessageSchema)).not.toThrow();
});
test('should compile OB11ActionMessageSchema without duplicate id error', () => {
expect(() => TypeCompiler.Compile(OB11ActionMessageSchema)).not.toThrow();
});
test('should compile OB11PostSendMsgSchema without error', () => {
expect(() => TypeCompiler.Compile(OB11PostSendMsgSchema)).not.toThrow();
});
test('should compile QuickAction hybrid schema without error', () => {
const QASchema = Type.Object({
message: OB11PostSendMsgSchema,
quick_action: OB11ActionMessageSchema,
});
expect(() => TypeCompiler.Compile(QASchema)).not.toThrow();
});
});
describe('SnowCat Schemas Validation & Coercion', () => {
test('should coerce numeric user_id to string in OB11PostSendMsgSchema', () => {
const payload = {
message_type: 'private',
user_id: 123456,
message: [{ type: 'text', data: { text: 'hello' } }],
};
let data: unknown = structuredClone(payload);
data = Value.Parse(OB11PostSendMsgSchema, data);
const compiler = TypeCompiler.Compile(OB11PostSendMsgSchema);
expect(compiler.Check(data)).toBe(true);
expect((data as Record<string, unknown>)['user_id']).toBe('123456');
});
test('should validate complex mixed messages correctly', () => {
const payload = {
message_type: 'group',
group_id: '654321',
message: 'this is a string message',
};
let data: unknown = structuredClone(payload);
data = Value.Parse(OB11PostSendMsgSchema, data);
const compiler = TypeCompiler.Compile(OB11PostSendMsgSchema);
expect(compiler.Check(data)).toBe(true);
});
});
describe('SnowCat Configuration Loaders', () => {
test('OneBotConfig schemas should compile', () => {
expect(() => TypeCompiler.Compile(OneBotConfigSchema)).not.toThrow();
});
test('OneBotConfig should load and apply defaults correctly', () => {
const partialConfig: Partial<OneBotConfig> = {
network: {
httpServers: [{
port: 3000,
enable: true,
name: 'test',
host: '127.0.0.1',
enableCors: true,
enableWebsocket: false,
messagePostFormat: 'array',
token: '',
debug: false,
}],
httpSseServers: [],
httpClients: [],
websocketServers: [],
websocketClients: [],
plugins: [],
},
};
const loaded = loadOneBotConfig(partialConfig);
expect(loaded.network.httpServers[0]?.host).toBe('127.0.0.1');
expect(loaded.network.httpServers[0]?.enableCors).toBe(true);
expect(loaded.musicSignUrl).toBe('');
});
test('OneBotConfig websocketClients should apply verifyCertificate default', () => {
const partialConfig: Partial<OneBotConfig> = {
network: {
httpServers: [],
httpSseServers: [],
httpClients: [],
websocketServers: [],
websocketClients: [{
name: 'test-ws-client',
enable: true,
url: 'wss://example.com',
messagePostFormat: 'array',
reportSelfMessage: false,
reconnectInterval: 5000,
token: '',
debug: false,
heartInterval: 30000,
}],
plugins: [],
},
};
const loaded = loadOneBotConfig(partialConfig);
expect(loaded.network.websocketClients[0]?.verifyCertificate).toBe(true);
});
test('OneBotConfig websocketClients should preserve explicit verifyCertificate false', () => {
const partialConfig: Partial<OneBotConfig> = {
network: {
httpServers: [],
httpSseServers: [],
httpClients: [],
websocketServers: [],
websocketClients: [{
name: 'test-ws-client',
enable: true,
url: 'wss://example.com',
messagePostFormat: 'array',
reportSelfMessage: false,
reconnectInterval: 5000,
token: '',
debug: false,
heartInterval: 30000,
verifyCertificate: false,
}],
plugins: [],
},
};
const loaded = loadOneBotConfig(partialConfig);
expect(loaded.network.websocketClients[0]?.verifyCertificate).toBe(false);
});
test('NapcatConfig should compile and apply defaults', () => {
let compiled: ReturnType<typeof TypeCompiler.Compile> | undefined;
expect(() => {
compiled = TypeCompiler.Compile(SnowCatConfigSchema);
}).not.toThrow();
let data: unknown = {};
data = Value.Parse(SnowCatConfigSchema, data);
expect(compiled?.Check(data)).toBe(true);
const resolved = data as Record<string, unknown>;
expect(resolved['consoleLog']).toBe(true);
expect(resolved['consoleLogLevel']).toBe('info');
});
});