import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; import 'package:dio/dio.dart'; import '../../api/model/create_task.dart'; import '../../api/model/create_task_batch.dart'; import '../../api/model/downloader_config.dart'; import '../../api/model/extension.dart'; import '../../api/model/http_listen_result.dart'; import '../../api/model/info.dart'; import '../../api/model/install_extension.dart'; import '../../api/model/request.dart'; import '../../api/model/resolve_result.dart'; import '../../api/model/result.dart'; import '../../api/model/switch_extension.dart'; import '../../api/model/task.dart'; import '../../api/model/task_filter.dart'; import '../../api/model/update_check_extension_resp.dart'; import '../../api/model/update_extension_settings.dart'; import '../../util/extensions.dart'; import '../../util/util.dart'; import '../libgopeed_boot.dart'; import '../native/channel/libgopeed_channel.dart'; import '../native/ffi/libgopeed_bind.dart'; import '../native/ffi/libgopeed_ffi.dart'; import '../native/libgopeed_interface.dart'; import '../native/model/invoke_request.dart'; import '../native/model/start_config.dart'; import 'libgopeed_boot_base.dart'; LibgopeedBoot create() => LibgopeedBootNative(); class LibgopeedBootNative with LibgopeedBootBase implements LibgopeedBoot, LibgopeedApi { late LibgopeedAbi _libgopeedAbi; late Dio _dio; LibgopeedBootNative() { if (Util.isDesktop()) { var libName = "libgopeed."; if (Platform.isWindows) { libName += "dll"; } if (Platform.isMacOS) { libName += "dylib"; } if (Platform.isLinux) { libName += "so"; } _libgopeedAbi = LibgopeedFFi(LibgopeedBind(DynamicLibrary.open(libName))); } else { _libgopeedAbi = LibgopeedChannel(); } } Future _invoke( String method, List params, T Function(dynamic json)? fromJsonT, ) async { final invokeRequest = InvokeRequest(method: method, params: params); final resp = await _libgopeedAbi.invoke(jsonEncode(invokeRequest)); final result = Result.fromJson(jsonDecode(resp), fromJsonT ??= (json) => null as T); return handleResult(result); } List _parseTaskFilter(TaskFilter? filter) { if (filter == null) { return [null]; } return [filter]; } @override Future init(StartConfig cfg) async { await _libgopeedAbi.init(jsonEncode(cfg.toJson())); _dio = createDio(); return this; } @override Future startHttp() async { return _invoke( "StartHttp", [], (json) => HttpListenResult.fromJson(json)); } @override Future stopHttp() async { await _invoke("StopHttp", [], null); } @override Future restartHttp() async { await _invoke("RestartHttp", [], null); } @override Future info() async { return _invoke("Info", [], (json) => Info.fromJson(json)); } @override Future resolve(Request request) async { return _invoke( "Resolve", [request], (json) => ResolveResult.fromJson(json)); } @override Future createTask(CreateTask createTask) async { return _invoke( "CreateTask", [createTask], (json) => json as String); } @override Future createTaskBatch(CreateTaskBatch createTask) async { return _invoke( "CreateTaskBatch", [createTask], (json) => json as String); } @override Future pauseTask(String id) async { await _invoke("PauseTask", [id], null); } @override Future pauseTasks(TaskFilter? filter) async { await _invoke("PauseTasks", _parseTaskFilter(filter), null); } @override Future continueTask(String id) async { await _invoke("ContinueTask", [id], null); } @override Future continueTasks(TaskFilter? filter) async { await _invoke("ContinueTasks", _parseTaskFilter(filter), null); } @override Future deleteTask(String id, bool force) async { await _invoke("DeleteTask", [id, force], null); } @override Future deleteTasks(TaskFilter? filter, bool force) async { await _invoke( "DeleteTasks", _parseTaskFilter(filter).apply((it) { it.add(force); }), null); } @override Future getTask(String id) async { return _invoke("GetTask", [id], (json) => Task.fromJson(json)); } @override Future> getTasks(TaskFilter? filter) async { return _invoke>("GetTasks", _parseTaskFilter(filter), (json) => (json as List).map((e) => Task.fromJson(e)).toList()); } @override Future> getTaskStats(String id) async { return _invoke>( "GetTaskStats", [id], (json) => json as Map); } @override Future getConfig() async { return _invoke( "GetConfig", [], (json) => DownloaderConfig.fromJson(json)); } @override Future putConfig(DownloaderConfig config) async { await _invoke("PutConfig", [config], null); } @override Future installExtension(InstallExtension installExtension) async { await _invoke("InstallExtension", [installExtension], null); } @override Future> getExtensions() async { return _invoke>("GetExtensions", [], (json) => (json as List).map((e) => Extension.fromJson(e)).toList()); } @override Future updateExtensionSettings( String identity, UpdateExtensionSettings updateExtensionSettings) async { await _invoke( "UpdateExtensionSettings", [identity, updateExtensionSettings], null); } @override Future switchExtension( String identity, SwitchExtension switchExtension) async { await _invoke("SwitchExtension", [identity, switchExtension], null); } @override Future deleteExtension(String identity) async { await _invoke("DeleteExtension", [identity], null); } @override Future upgradeCheckExtension( String identity) async { return _invoke("UpgradeCheckExtension", [identity], (json) => UpdateCheckExtensionResp.fromJson(json)); } @override Future upgradeExtension(String identity) async { await _invoke("UpgradeExtension", [identity], null); } @override Future close() async { await _invoke("Close", [], null); } @override Future> proxyRequest(String uri, {data, Options? options}) { return _dio.request(uri, data: data, options: options); } }