184 lines
4.6 KiB
Dart
184 lines
4.6 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:dio/dio.dart';
|
|
import 'package:fl_clash/clash/clash.dart';
|
|
import 'package:fl_clash/common/common.dart';
|
|
import 'package:fl_clash/models/models.dart';
|
|
import 'package:fl_clash/state.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
class Request {
|
|
late final Dio _dio;
|
|
String? userAgent;
|
|
|
|
Request() {
|
|
_dio = Dio();
|
|
_dio.interceptors.add(
|
|
InterceptorsWrapper(
|
|
onRequest: (options, handler) {
|
|
return handler.next(options); // 继续请求
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<Response> getFileResponseForUrl(String url) async {
|
|
final response = await _dio
|
|
.get(
|
|
url,
|
|
options: Options(
|
|
headers: {
|
|
"User-Agent": globalState.appController.clashConfig.globalUa
|
|
},
|
|
responseType: ResponseType.bytes,
|
|
),
|
|
)
|
|
.timeout(
|
|
httpTimeoutDuration * 6,
|
|
);
|
|
return response;
|
|
}
|
|
|
|
Future<MemoryImage?> getImage(String url) async {
|
|
if (url.isEmpty) return null;
|
|
final response = await _dio.get<Uint8List>(
|
|
url,
|
|
options: Options(
|
|
responseType: ResponseType.bytes,
|
|
),
|
|
);
|
|
final data = response.data;
|
|
if (data == null) return null;
|
|
return MemoryImage(data);
|
|
}
|
|
|
|
Future<Map<String, dynamic>?> checkForUpdate() async {
|
|
final response = await _dio.get(
|
|
"https://api.github.com/repos/$repository/releases/latest",
|
|
options: Options(
|
|
responseType: ResponseType.json,
|
|
),
|
|
);
|
|
if (response.statusCode != 200) return null;
|
|
final data = response.data as Map<String, dynamic>;
|
|
final remoteVersion = data['tag_name'];
|
|
final version = globalState.packageInfo.version;
|
|
final hasUpdate =
|
|
other.compareVersions(remoteVersion.replaceAll('v', ''), version) > 0;
|
|
if (!hasUpdate) return null;
|
|
return data;
|
|
}
|
|
|
|
final List<String> _ipInfoSources = [
|
|
"https://ipwho.is/?fields=ip&output=csv",
|
|
"https://ipinfo.io/ip",
|
|
"https://ifconfig.me/ip/",
|
|
];
|
|
|
|
Future<IpInfo?> checkIp({CancelToken? cancelToken}) async {
|
|
for (final source in _ipInfoSources) {
|
|
try {
|
|
final response = await _dio
|
|
.get<String>(
|
|
source,
|
|
cancelToken: cancelToken,
|
|
)
|
|
.timeout(httpTimeoutDuration);
|
|
if (response.statusCode != 200 || response.data == null) {
|
|
continue;
|
|
}
|
|
final ipInfo = await clashCore.getCountryCode(response.data!);
|
|
if (ipInfo == null && source != _ipInfoSources.last) {
|
|
continue;
|
|
}
|
|
return ipInfo;
|
|
} catch (e) {
|
|
debugPrint("checkIp error ===> $e");
|
|
if (e is DioException && e.type == DioExceptionType.cancel) {
|
|
throw "cancelled";
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Future<bool> pingHelper() async {
|
|
try {
|
|
final response = await _dio
|
|
.get(
|
|
"http://$localhost:$helperPort/ping",
|
|
options: Options(
|
|
responseType: ResponseType.plain,
|
|
),
|
|
)
|
|
.timeout(
|
|
const Duration(
|
|
milliseconds: 2000,
|
|
),
|
|
);
|
|
if (response.statusCode != HttpStatus.ok) {
|
|
return false;
|
|
}
|
|
return (response.data as String) == helperTag;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> startCoreByHelper(String arg) async {
|
|
try {
|
|
final response = await _dio
|
|
.post(
|
|
"http://$localhost:$helperPort/start",
|
|
data: json.encode({
|
|
"path": appPath.corePath,
|
|
"arg": arg,
|
|
}),
|
|
options: Options(
|
|
responseType: ResponseType.plain,
|
|
),
|
|
)
|
|
.timeout(
|
|
const Duration(
|
|
milliseconds: 2000,
|
|
),
|
|
);
|
|
if (response.statusCode != HttpStatus.ok) {
|
|
return false;
|
|
}
|
|
final data = response.data as String;
|
|
return data.isEmpty;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> stopCoreByHelper() async {
|
|
try {
|
|
final response = await _dio
|
|
.post(
|
|
"http://$localhost:$helperPort/stop",
|
|
options: Options(
|
|
responseType: ResponseType.plain,
|
|
),
|
|
)
|
|
.timeout(
|
|
const Duration(
|
|
milliseconds: 2000,
|
|
),
|
|
);
|
|
if (response.statusCode != HttpStatus.ok) {
|
|
return false;
|
|
}
|
|
final data = response.data as String;
|
|
return data.isEmpty;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
final request = Request();
|