import { Type, Static } from '@sinclair/typebox'; import { TypeCompiler } from '@sinclair/typebox/compiler'; import { Value } from '@sinclair/typebox/value'; export type MessageFormat = 'array' | 'string'; const HttpServerConfigSchema = Type.Object({ name: Type.String({ default: 'http-server' }), enable: Type.Boolean({ default: false }), port: Type.Number({ default: 3000 }), host: Type.String({ default: '127.0.0.1' }), enableCors: Type.Boolean({ default: true }), enableWebsocket: Type.Boolean({ default: false }), messagePostFormat: Type.String({ default: 'array' }), token: Type.String({ default: '' }), debug: Type.Boolean({ default: false }), }); const HttpSseServerConfigSchema = Type.Object({ name: Type.String({ default: 'http-sse-server' }), enable: Type.Boolean({ default: false }), port: Type.Number({ default: 3000 }), host: Type.String({ default: '127.0.0.1' }), enableCors: Type.Boolean({ default: true }), enableWebsocket: Type.Boolean({ default: false }), messagePostFormat: Type.String({ default: 'array' }), token: Type.String({ default: '' }), debug: Type.Boolean({ default: false }), reportSelfMessage: Type.Boolean({ default: false }), }); const HttpClientConfigSchema = Type.Object({ name: Type.String({ default: 'http-client' }), enable: Type.Boolean({ default: false }), url: Type.String({ default: 'http://localhost:8080' }), messagePostFormat: Type.String({ default: 'array' }), reportSelfMessage: Type.Boolean({ default: false }), token: Type.String({ default: '' }), debug: Type.Boolean({ default: false }), }); const WebsocketServerConfigSchema = Type.Object({ name: Type.String({ default: 'websocket-server' }), enable: Type.Boolean({ default: false }), host: Type.String({ default: '127.0.0.1' }), port: Type.Number({ default: 3001 }), messagePostFormat: Type.String({ default: 'array' }), reportSelfMessage: Type.Boolean({ default: false }), token: Type.String({ default: '' }), enableForcePushEvent: Type.Boolean({ default: true }), debug: Type.Boolean({ default: false }), heartInterval: Type.Number({ default: 30000 }), }); const WebsocketClientConfigSchema = Type.Object({ name: Type.String({ default: 'websocket-client' }), enable: Type.Boolean({ default: false }), url: Type.String({ default: 'ws://localhost:8082' }), messagePostFormat: Type.String({ default: 'array' }), reportSelfMessage: Type.Boolean({ default: false }), reconnectInterval: Type.Number({ default: 5000 }), token: Type.String({ default: '' }), debug: Type.Boolean({ default: false }), heartInterval: Type.Number({ default: 30000 }), verifyCertificate: Type.Optional(Type.Boolean({ default: true })), }); const PluginConfigSchema = Type.Object({ name: Type.String({ default: 'plugin' }), enable: Type.Boolean({ default: false }), messagePostFormat: Type.String({ default: 'array' }), reportSelfMessage: Type.Boolean({ default: false }), debug: Type.Boolean({ default: false }), }); const McpServerConfigSchema = Type.Object({ name: Type.String({ default: 'mcp-server' }), enable: Type.Boolean({ default: false }), host: Type.String({ default: '127.0.0.1' }), port: Type.Number({ default: 3002 }), token: Type.String({ default: '' }), debug: Type.Boolean({ default: false }), }); const NetworkConfigSchema = Type.Object({ httpServers: Type.Array(HttpServerConfigSchema, { default: [] }), httpSseServers: Type.Array(HttpSseServerConfigSchema, { default: [] }), httpClients: Type.Array(HttpClientConfigSchema, { default: [] }), websocketServers: Type.Array(WebsocketServerConfigSchema, { default: [] }), websocketClients: Type.Array(WebsocketClientConfigSchema, { default: [] }), mcpServers: Type.Optional(Type.Array(McpServerConfigSchema, { default: [] })), plugins: Type.Array(PluginConfigSchema, { default: [] }), }, { default: {} }); const TimeoutConfigSchema = Type.Object({ baseTimeout: Type.Number({ default: 10000 }), uploadSpeedKBps: Type.Number({ default: 256 }), downloadSpeedKBps: Type.Number({ default: 256 }), maxTimeout: Type.Number({ default: 1800000 }), }, { default: {} }); export const OneBotConfigSchema = Type.Object({ network: NetworkConfigSchema, musicSignUrl: Type.String({ default: '' }), enableLocalFile2Url: Type.Boolean({ default: false }), parseMultMsg: Type.Boolean({ default: false }), imageDownloadProxy: Type.String({ default: '' }), timeout: TimeoutConfigSchema, }); export type OneBotConfig = Static; export type HttpServerConfig = Static; export type HttpSseServerConfig = Static; export type HttpClientConfig = Static; export type WebsocketServerConfig = Static; export type WebsocketClientConfig = Static; export type PluginConfig = Static; export type McpServerConfig = Static; export type NetworkAdapterConfig = HttpServerConfig | HttpSseServerConfig | HttpClientConfig | WebsocketServerConfig | WebsocketClientConfig | McpServerConfig | PluginConfig; export type NetworkConfigKey = keyof OneBotConfig['network']; export function loadConfig (config: Partial): OneBotConfig { let data = config; data = Value.Parse(OneBotConfigSchema, data) as Partial; const validate = TypeCompiler.Compile(OneBotConfigSchema); const valid = validate.Check(data); if (!valid) { const errorMsg = [...validate.Errors(data)].map(e => e.message).join(', '); throw new Error(errorMsg); } return data as OneBotConfig; } export function calculateTimeout ( config: OneBotConfig['timeout'], dataSizeBytes: number, speedKBps: number ): number { return Math.min( config.baseTimeout + (dataSizeBytes / 1024 / Math.max(speedKBps, 1) * 1000), config.maxTimeout ); } export function capTimeout ( config: OneBotConfig['timeout'], timeoutMs: number ): number { return Math.min(timeoutMs, config.maxTimeout); }