import 'package:dio/dio.dart'; import 'package:get/get.dart'; import 'package:naiyouwl/app/bean/clash_core.dart'; import 'package:naiyouwl/app/bean/connect.dart'; import 'package:naiyouwl/app/bean/proxie.dart'; import 'package:naiyouwl/app/bean/rule.dart'; import 'package:naiyouwl/app/common/LogHelper.dart'; import 'package:naiyouwl/app/controller/controllers.dart'; import 'package:naiyouwl/app/utils/system_proxy.dart'; import 'package:web_socket_channel/io.dart'; class CoreController extends GetxController { late final dio = Dio(BaseOptions( baseUrl: 'http://127.0.0.1:9799', )); late final LogHelper _logger = LogHelper(); var version = ClashCoreVersion(premium: true, version: '').obs; var address = ''.obs; var secret = ''.obs; var config = ClashCoreConfig( port: 0, socksPort: 0, redirPort: 0, tproxyPort: 0, mixedPort: 0, allowLan: false, bindAddress: '', mode: 'rule', logLevel: '', ipv6: false, ).obs; var ruleProvider = RuleProvider(providers: {}).obs; var rule = Rule(rules: []).obs; CoreController(){ // dio.interceptors.add(LogInterceptor( // request: true, // requestBody: true, // responseBody: true, // error: true, // logPrint: _logger.d, // 使用 Logger 插件打印日志 // )); //dio.interceptors.add(FriendlyErrorInterceptor()); } SystemProxyConfig get proxyConfig { final mixedPort = config.value.mixedPort == 0 ? null : config.value.mixedPort; final httpPort = mixedPort ?? config.value.port; final httpsPort = mixedPort ?? config.value.port; final socksPort = mixedPort ?? config.value.socksPort; return SystemProxyConfig( http: httpPort == 0 ? null : '127.0.0.1:$httpPort', https: httpsPort == 0 ? null : '127.0.0.1:$httpsPort', socks: socksPort == 0 ? null : '127.0.0.1:$socksPort', ); } setApi(String apiAddress, String apiSecret) { address.value = apiAddress; secret.value = apiSecret; dio.options.baseUrl = 'http://${address.value}'; dio.options.headers['Authorization'] = 'Bearer ${secret.value}'; } Future fetchHello() async { return await dio.get('/'); } Future updateVersion() async { final res = await dio.get('/version'); version.value = ClashCoreVersion.fromJson(res.data); } Future updateConfig() async { final res = await dio.get('/configs'); config.value = ClashCoreConfig.fromJson(res.data); LogHelper().d("update-config ${config.value}"); } Future fetchConfigUpdate(Map config) async { await dio.patch('/configs', data: config); await updateConfig(); } // type updateConfigRequest struct { // Path string `json:"path"` // Payload string `json:"payload"` // } // https://github.com/Dreamacro/clash/blob/c231fd14666d6ea05d6a75eaba6db69f9eee5ae9/hub/route/configs.go#L95 Future fetchReloadConfig(Map config) async { await dio.put('/configs', data: config); } Future fetchCloseConnections(String id) async { await dio.delete('/connections/${Uri.encodeComponent(id)}'); } IOWebSocketChannel fetchConnectionsWs() { return IOWebSocketChannel.connect( Uri.parse('ws://${address.value}/connections'), headers: {"Authorization": dio.options.headers["Authorization"]}, ); } Future updateRuleProvider() async { final res = await dio.get('/providers/rules'); ruleProvider.value = RuleProvider.fromJson(res.data); ruleProvider.refresh(); } Future updateRule() async { final res = await dio.get('/rules'); rule.value = Rule.fromJson(res.data); rule.refresh(); } Future fetchRuleProviderUpdate(String name) async { await dio.put('/providers/rules/${Uri.encodeComponent(name)}'); } Future fetchProxie() async { final res = await dio.get('/proxies'); return Proxie.fromJson(res.data); } Future fetchProxieProvider() async { final res = await dio.get('/providers/proxies'); return ProxieProvider.fromJson(res.data); } Future fetchProxieProviderHealthCheck(String provider) async { await dio.get('/providers/proxies/${Uri.encodeComponent(provider)}/healthcheck'); } Future fetchSetProxieGroup(String group, String value) async { await dio.put('/proxies/${Uri.encodeComponent(group)}', data: {'name': value}); } Future fetchProxieProviderUpdate(String name) async { await dio.put('/providers/proxies/${Uri.encodeComponent(name)}'); } Future fetchProxieDelay(String name) async { final query = {'timeout': 5000, 'url': 'http://www.gstatic.com/generate_204'}; final res = await dio.get('/proxies/${Uri.encodeComponent(name)}/delay', queryParameters: query); return res.data['delay'] ?? 0; } Future fetchConnection() async { final res = await dio.get('/connections'); if(res.data !=null){ LogHelper().d("没有连接"); //return Connect(); } return Connect.fromJson(res.data); } } class FriendlyErrorInterceptor extends Interceptor { @override Future onError(DioError err, ErrorInterceptorHandler handler) async { String message = 'core未知错误'; if (err.type == DioErrorType.connectTimeout || err.type == DioErrorType.sendTimeout || err.type == DioErrorType.receiveTimeout) { message = '连接core超时,请检查您的网络'; } else if (err.type == DioErrorType.cancel) { message = 'core 请求已被取消'; } else if (err.type == DioErrorType.response) { message = 'core 服务端响应错误: ${err.response?.statusCode} ${err.response?.statusMessage}'; } else if (err.type == DioErrorType.other) { message = 'core 其他错误: ${err.message}'; } LogHelper().d(message); return DioError(error: message, requestOptions: err.requestOptions); } }