core.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. import 'dart:convert';
  2. import 'package:get/get.dart';
  3. import 'package:naiyouwl/app/bean/clash_core.dart';
  4. import 'package:naiyouwl/app/bean/connect.dart';
  5. import 'package:naiyouwl/app/bean/rule.dart';
  6. import 'package:naiyouwl/app/common/LogHelper.dart';
  7. import 'package:naiyouwl/app/utils/system_proxy.dart';
  8. import 'package:web_socket_channel/io.dart';
  9. import 'package:http/http.dart' as http;
  10. class CoreController extends GetxController {
  11. // late final dio = Dio(BaseOptions(
  12. // baseUrl: 'http://127.0.0.1:9799',
  13. // ));
  14. var ip = "127.0.0.1";
  15. var url = "";
  16. var client = http.Client();
  17. var headers = Map<String,String>();
  18. late final LogHelper _logger = LogHelper();
  19. var version = ClashCoreVersion(premium: true, version: '').obs;
  20. var address = ''.obs;
  21. var secret = ''.obs;
  22. var config = ClashCoreConfig(
  23. port: 0,
  24. socksPort: 0,
  25. redirPort: 0,
  26. tproxyPort: 0,
  27. mixedPort: 0,
  28. allowLan: false,
  29. bindAddress: '',
  30. mode: 'rule',
  31. logLevel: '',
  32. ipv6: false,
  33. ).obs;
  34. var ruleProvider = RuleProvider(providers: {}).obs;
  35. var rule = Rule(rules: []).obs;
  36. CoreController(){
  37. // dio.interceptors.add(LogInterceptor(
  38. // request: true,
  39. // requestBody: true,
  40. // responseBody: true,
  41. // error: true,
  42. // logPrint: _logger.d, // 使用 Logger 插件打印日志
  43. // ));
  44. //dio.interceptors.add(FriendlyErrorInterceptor());
  45. }
  46. SystemProxyConfig get proxyConfig {
  47. final mixedPort = config.value.mixedPort == 0 ? null : config.value.mixedPort;
  48. final httpPort = mixedPort ?? config.value.port;
  49. final httpsPort = mixedPort ?? config.value.port;
  50. final socksPort = mixedPort ?? config.value.socksPort;
  51. return SystemProxyConfig(
  52. http: httpPort == 0 ? null : '127.0.0.1:$httpPort',
  53. https: httpsPort == 0 ? null : '127.0.0.1:$httpsPort',
  54. socks: socksPort == 0 ? null : '127.0.0.1:$socksPort',
  55. );
  56. }
  57. setApi(String apiAddress, String apiSecret) {
  58. address.value = apiAddress;
  59. secret.value = apiSecret;
  60. // dio.close(force: true);
  61. url = "${address.value}";
  62. headers["Authorization"] = 'Bearer ${secret.value}';
  63. //client.head(Uri.http(url,'info'))
  64. // dio.options.baseUrl = 'http://${address.value}';
  65. // print("dio baseUrl api ${dio.options.baseUrl}");
  66. // dio.options.headers['Authorization'] = 'Bearer ${secret.value}';
  67. }
  68. Future<dynamic> fetchHello() async {
  69. try {
  70. var ut = Uri.parse('http://$url/info');
  71. final res = await client.get(ut,headers: headers);
  72. if(res.statusCode == 200) {
  73. var jsonResponse =
  74. jsonDecode(res.body) as Map<String, dynamic>;
  75. return jsonResponse;
  76. }
  77. } on http.ClientException catch (e) {
  78. // 处理客户端异常,例如没有网络连接
  79. print('Client fetchHello Exception: ${e.message}');
  80. return null;
  81. } on Exception catch (e) {
  82. // 处理其他类型的异常
  83. print('Exception: $e');
  84. return null;
  85. }
  86. }
  87. Future<ClashCoreVersion?> updateVersion() async {
  88. try {
  89. var ut = Uri.parse('http://$url/version');
  90. final res = await client.get(ut,headers: headers);
  91. if(res.statusCode == 200) {
  92. var jsonResponse =
  93. jsonDecode(res.body) as Map<String, dynamic>;
  94. version.value = ClashCoreVersion.fromJson(jsonResponse);
  95. return version.value;
  96. }
  97. } on http.ClientException catch (e) {
  98. // 处理客户端异常,例如没有网络连接
  99. print('Client updateVersion Exception: ${e.message}');
  100. return null;
  101. } on Exception catch (e) {
  102. // 处理其他类型的异常
  103. print('Exception: $e');
  104. return null;
  105. }
  106. return null;
  107. }
  108. Future<void> updateConfig() async {
  109. try {
  110. var ut = Uri.parse('http://$url/configs');
  111. final res = await client.get(ut,headers: headers);
  112. print("updateConfig ---- ${res.statusCode}");
  113. if(res.statusCode == 200) {
  114. var jsonResponse =
  115. jsonDecode(res.body) as Map<String, dynamic>;
  116. config.value = ClashCoreConfig.fromJson(jsonResponse);
  117. }
  118. } on http.ClientException catch (e) {
  119. // 处理客户端异常,例如没有网络连接
  120. print('Client updateConfig Exception: ${e.message}');
  121. } on Exception catch (e) {
  122. // 处理其他类型的异常
  123. print('Exception updateConfig: $e');
  124. }
  125. }
  126. Future<void> fetchConfigUpdate(Map<String, dynamic> config) async {
  127. try {
  128. ///configs
  129. ///
  130. // {"mode":"global"}
  131. //请求 URL:
  132. // http://127.0.0.1:9799/configs
  133. // 请求方法:
  134. // PATCH
  135. var ut = Uri.parse('http://$url/configs');
  136. final res = await client.patch(ut, headers: headers, body: jsonEncode(config));
  137. print("fetchConfigUpdate ---- ${res.statusCode}");
  138. if (res.statusCode == 204) {
  139. print("配置更新成功");
  140. } else {
  141. print("配置更新失败,状态码: ${res.statusCode}");
  142. }
  143. // var jsonResponse =
  144. // jsonDecode(res.body) as Map<String, dynamic>;
  145. // print(jsonResponse);
  146. await updateConfig();
  147. } on http.ClientException catch (e) {
  148. // 处理客户端异常,例如没有网络连接
  149. print('Client fetchConfigUpdate Exception: ${e.message}');
  150. } on Exception catch (e) {
  151. // 处理其他类型的异常
  152. print('Exception fetchConfigUpdate: $e');
  153. }
  154. }
  155. Future<void> changeConfig(String configPath) async{
  156. for (var i = 0 ; i< 5; i++) {
  157. try {
  158. final body = json.encode({
  159. "path": configPath
  160. });
  161. var ut = Uri.parse('http://$url/configs');
  162. final res = await client.put(ut,body:body,headers: headers);
  163. print("changeConfig ---- ${res.statusCode}");
  164. if(res.statusCode == 204)
  165. {
  166. await updateConfig();
  167. break;
  168. }
  169. } on http.ClientException catch (e) {
  170. // 处理客户端异常,例如没有网络连接
  171. print('Client changeConfig Exception: ${e.message}');
  172. continue;
  173. } on Exception catch (e) {
  174. // 处理其他类型的异常
  175. print('Exception changeConfig : $e');
  176. continue;
  177. }
  178. }
  179. }
  180. Future<void> restartConfig(String configPath) async{
  181. try {
  182. final body = json.encode({
  183. "path": configPath
  184. });
  185. var ut = Uri.parse('http://$url/restart');
  186. final res = await client.put(ut,body:body,headers: headers);
  187. print("changeConfig ---- ${res.statusCode}");
  188. if(res.statusCode == 204)
  189. {
  190. await updateConfig();
  191. }
  192. } on http.ClientException catch (e) {
  193. } on Exception catch (e) {
  194. }
  195. }
  196. // type updateConfigRequest struct {
  197. // Path string `json:"path"`
  198. // Payload string `json:"payload"`
  199. // }
  200. // https://github.com/Dreamacro/clash/blob/c231fd14666d6ea05d6a75eaba6db69f9eee5ae9/hub/route/configs.go#L95
  201. // Future<void> fetchReloadConfig(Map<String, String> config) async {
  202. // print("fetchReloadConfig $config");
  203. // await dio.put('/configs', data: config);
  204. // }
  205. Future<void> fetchCloseConnections(String id) async {
  206. //await dio.delete('/connections/${Uri.encodeComponent(id)}');
  207. try {
  208. var ut = Uri.parse('http://$url/connections/${Uri.encodeComponent(id)}');
  209. final res = await client.delete(ut,headers: headers);
  210. print("fetchCloseConnections ---- ${res.statusCode}");
  211. if(res.statusCode == 204){
  212. var jsonResponse =
  213. jsonDecode(res.body) as Map<String, dynamic>;
  214. print(jsonResponse);
  215. await updateConfig();
  216. }
  217. } on http.ClientException catch (e) {
  218. // 处理客户端异常,例如没有网络连接
  219. print('Client fetchCloseConnections Exception: ${e.message}');
  220. } on Exception catch (e) {
  221. // 处理其他类型的异常
  222. print('Exception: $e');
  223. }
  224. }
  225. IOWebSocketChannel fetchConnectionsWs() {
  226. return IOWebSocketChannel.connect(
  227. Uri.parse('ws://${address.value}/connections'),
  228. headers: headers,
  229. );
  230. }
  231. Future updateRuleProvider() async {
  232. // final res = await dio.get('/providers/rules');
  233. // ruleProvider.value = RuleProvider.fromJson(res.data);
  234. // ruleProvider.refresh();
  235. try {
  236. var ut = Uri.parse('http://$url/poviders/rules');
  237. final res = await client.get(ut,headers: headers);
  238. if(res.statusCode == 200){
  239. var jsonResponse =
  240. jsonDecode(res.body) as Map<String, dynamic>;
  241. ruleProvider.value = RuleProvider.fromJson(jsonResponse);
  242. ruleProvider.refresh();
  243. }
  244. } on http.ClientException catch (e) {
  245. // 处理客户端异常,例如没有网络连接
  246. print('Client updateRuleProvider Exception: ${e.message}');
  247. } on Exception catch (e) {
  248. // 处理其他类型的异常
  249. print('Exception: $e');
  250. }
  251. }
  252. Future updateRule() async {
  253. // final res = await dio.get('/rules');
  254. // rule.value = Rule.fromJson(res.data);
  255. // rule.refresh();
  256. try {
  257. var ut = Uri.parse('http://$url/rules');
  258. final res = await client.get(ut,headers: headers);
  259. if(res.statusCode == 200){
  260. var jsonResponse =
  261. jsonDecode(res.body) as Map<String, dynamic>;
  262. rule.value = Rule.fromJson(jsonResponse);
  263. rule.refresh();
  264. }
  265. } on http.ClientException catch (e) {
  266. // 处理客户端异常,例如没有网络连接
  267. print('Client updateRule Exception: ${e.message}');
  268. } on Exception catch (e) {
  269. // 处理其他类型的异常
  270. print('Exception: $e');
  271. }
  272. }
  273. // Future<void> fetchRuleProviderUpdate(String name) async {
  274. // await dio.put('/providers/rules/${Uri.encodeComponent(name)}');
  275. // }
  276. // Future<Proxie> fetchProxie() async {
  277. // final res = await dio.get('/proxies');
  278. // return Proxie.fromJson(res.data);
  279. // }
  280. // Future<ProxieProvider> fetchProxieProvider() async {
  281. // final res = await dio.get('/providers/proxies');
  282. // return ProxieProvider.fromJson(res.data);
  283. // }
  284. // Future<void> fetchProxieProviderHealthCheck(String provider) async {
  285. // await dio.get('/providers/proxies/${Uri.encodeComponent(provider)}/healthcheck');
  286. // }
  287. Future<void> fetchSetProxieGroup(String group, String value) async {
  288. try {
  289. // 构建请求体
  290. final body = json.encode({
  291. 'name': value // 确认 value 是正确的代理名称
  292. });
  293. // 构建 URL,确保 group 是正确的代理组名称
  294. var ut = Uri.parse('http://$url/proxies/${Uri.encodeComponent(group)}');
  295. // 发起 PUT 请求,选择代理
  296. final ret = await client.put(ut, body: body, headers: headers);
  297. // 输出返回的状态码,确保请求成功
  298. print("fetchSetProxieGroup ${ret.statusCode}");
  299. // 检查状态码,确保请求成功
  300. if (ret.statusCode == 204) {
  301. print('Proxy group updated successfully.');
  302. } else {
  303. print('Failed to update proxy group: ${ret.statusCode}');
  304. }
  305. } on http.ClientException catch (e) {
  306. // 处理客户端异常,例如没有网络连接
  307. print('fetchSetProxieGroup ClientException: ${e.message}');
  308. } on Exception catch (e) {
  309. // 处理其他类型的异常
  310. print('fetchSetProxieGroup Exception: $e');
  311. }
  312. }
  313. //
  314. // Future<void> fetchProxieProviderUpdate(String name) async {
  315. // await dio.put('/providers/proxies/${Uri.encodeComponent(name)}');
  316. // }
  317. // Future<int> fetchProxieDelay(String name) async {
  318. // final query = {'timeout': 5000, 'url': 'http://www.gstatic.com/generate_204'};
  319. // final res = await dio.get('/proxies/${Uri.encodeComponent(name)}/delay', queryParameters: query);
  320. // return res.data['delay'] ?? 0;
  321. // }
  322. //
  323. Future<Connect?> fetchConnection() async {
  324. // final res = await dio.get('/connections');
  325. // if(res.data !=null){
  326. // // LogHelper().d("没有连接");
  327. // //return Connect();
  328. // }
  329. try {
  330. var ut = Uri.parse('http://$url/connections');
  331. final res = await client.get(ut,headers: headers);
  332. if(res.statusCode == 200){
  333. var jsonResponse =
  334. jsonDecode(res.body) as Map<String, dynamic>;
  335. return Connect.fromJson(jsonResponse);
  336. }
  337. } on http.ClientException catch (e) {
  338. // 处理客户端异常,例如没有网络连接
  339. print('fetchConnection Exception: ${e.message}');
  340. return null;
  341. } on Exception catch (e) {
  342. // 处理其他类型的异常
  343. print('fetchConnection Exception: $e');
  344. return null;
  345. }
  346. }
  347. }