import 'dart:async'; import 'dart:convert'; import 'dart:isolate'; import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/models/models.dart'; mixin CoreInterface { Future init(InitParams params); Future preload(); Future shutdown(); Future get isInit; Future forceGc(); Future validateConfig(String path); Future getConfig(String path); Future asyncTestDelay(String url, String proxyName); Future updateConfig(UpdateParams updateParams); Future setupConfig(SetupParams setupParams); Future getProxies(); Future changeProxy(ChangeProxyParams changeProxyParams); Future startListener(); Future stopListener(); Future getExternalProviders(); Future? getExternalProvider(String externalProviderName); Future updateGeoData(UpdateGeoDataParams params); Future sideLoadExternalProvider({ required String providerName, required String data, }); Future updateExternalProvider(String providerName); FutureOr getTraffic(bool onlyStatisticsProxy); FutureOr getTotalTraffic(bool onlyStatisticsProxy); FutureOr getCountryCode(String ip); FutureOr getMemory(); FutureOr resetTraffic(); FutureOr startLog(); FutureOr stopLog(); Future crash(); FutureOr getConnections(); FutureOr closeConnection(String id); FutureOr deleteFile(String path); FutureOr closeConnections(); FutureOr resetConnections(); } abstract class CoreHandlerInterface with CoreInterface { Future get connected; FutureOr destroy(); Future _invoke({ required ActionMethod method, dynamic data, Duration? timeout, }) async { await connected; return invoke(method: method, data: data, timeout: timeout); } Future invoke({ required ActionMethod method, dynamic data, Duration? timeout, }); Future parasResult(ActionResult result) async { return switch (result.method) { ActionMethod.getConfig => result.toResult as T, _ => result.data as T, }; } @override Future init(InitParams params) async { return await _invoke( method: ActionMethod.initClash, data: json.encode(params), ) ?? false; } @override Future shutdown(); @override Future get isInit async { return await _invoke(method: ActionMethod.getIsInit) ?? false; } @override Future forceGc() async { return await _invoke(method: ActionMethod.forceGc) ?? false; } @override Future validateConfig(String path) async { return await _invoke( method: ActionMethod.validateConfig, data: path, ) ?? ''; } @override Future updateConfig(UpdateParams updateParams) async { return await _invoke( method: ActionMethod.updateConfig, data: json.encode(updateParams), ) ?? ''; } @override Future getConfig(String path) async { return await _invoke(method: ActionMethod.getConfig, data: path) ?? Result>.success({}); } @override Future setupConfig(SetupParams setupParams) async { final data = await Isolate.run(() => json.encode(setupParams)); return await _invoke( method: ActionMethod.setupConfig, data: data, ) ?? ''; } @override Future crash() async { return await _invoke(method: ActionMethod.crash) ?? false; } @override Future getProxies() async { final map = await _invoke(method: ActionMethod.getProxies); return map ?? {}; } @override Future changeProxy(ChangeProxyParams changeProxyParams) async { return await _invoke( method: ActionMethod.changeProxy, data: json.encode(changeProxyParams), ) ?? ''; } @override Future getExternalProviders() async { return await _invoke(method: ActionMethod.getExternalProviders) ?? ''; } @override Future getExternalProvider(String externalProviderName) async { return await _invoke( method: ActionMethod.getExternalProvider, data: externalProviderName, ) ?? ''; } @override Future updateGeoData(UpdateGeoDataParams params) async { return await _invoke( method: ActionMethod.updateGeoData, data: json.encode(params), ) ?? ''; } @override Future sideLoadExternalProvider({ required String providerName, required String data, }) async { return await _invoke( method: ActionMethod.sideLoadExternalProvider, data: json.encode({'providerName': providerName, 'data': data}), ) ?? ''; } @override Future updateExternalProvider(String providerName) async { return await _invoke( method: ActionMethod.updateExternalProvider, data: providerName, ) ?? ''; } @override Future getConnections() async { return await _invoke(method: ActionMethod.getConnections) ?? ''; } @override Future closeConnections() async { return await _invoke(method: ActionMethod.closeConnections) ?? false; } @override Future resetConnections() async { return await _invoke(method: ActionMethod.resetConnections) ?? false; } @override Future closeConnection(String id) async { return await _invoke( method: ActionMethod.closeConnection, data: id, ) ?? false; } @override Future getTotalTraffic(bool onlyStatisticsProxy) async { return await _invoke( method: ActionMethod.getTotalTraffic, data: onlyStatisticsProxy, ) ?? ''; } @override Future getTraffic(bool onlyStatisticsProxy) async { return await _invoke( method: ActionMethod.getTraffic, data: onlyStatisticsProxy, ) ?? ''; } @override Future deleteFile(String path) async { return await _invoke(method: ActionMethod.deleteFile, data: path) ?? ''; } @override resetTraffic() { _invoke(method: ActionMethod.resetTraffic); } @override startLog() { _invoke(method: ActionMethod.startLog); } @override stopLog() { _invoke(method: ActionMethod.stopLog); } @override Future startListener() async { return await _invoke(method: ActionMethod.startListener) ?? false; } @override Future stopListener() async { return await _invoke(method: ActionMethod.stopListener) ?? false; } @override Future asyncTestDelay(String url, String proxyName) async { final delayParams = { 'proxy-name': proxyName, 'timeout': httpTimeoutDuration.inMilliseconds, 'test-url': url, }; return await _invoke( method: ActionMethod.asyncTestDelay, data: json.encode(delayParams), timeout: Duration(seconds: 6), ) ?? json.encode(Delay(name: proxyName, value: -1, url: url)); } @override Future getCountryCode(String ip) async { return await _invoke( method: ActionMethod.getCountryCode, data: ip, ) ?? ''; } @override Future getMemory() async { return await _invoke(method: ActionMethod.getMemory) ?? ''; } }