import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'package:isekai_wiki/api/base_api.dart'; import 'package:isekai_wiki/global.dart'; import '../../utils/api_utils.dart'; class MWError { String? code; String? info; String? detail; MWError({this.code, this.info, this.detail}); static MWError fromMap(Map errorMap) { var mwError = MWError(); if (errorMap.containsKey("code")) { mwError.code = errorMap["code"].toString(); } if (errorMap.containsKey("info")) { mwError.info = errorMap["info"].toString(); } if (errorMap.containsKey("*")) { mwError.detail = errorMap["*"].toString(); } return mwError; } } class MWMultiError extends Error { List errorList; MWMultiError(this.errorList); @override String toString() { return errorList.map((e) => e.info).join("\n"); } } class MWResponse { bool ok = false; List? errorList; T? data; Map? continueInfo; MWResponse({this.ok = false, this.errorList, this.data, this.continueInfo}); } class MWApiClient extends http.BaseClient { final http.Client _inner; MWApiClient(this._inner); Future send(http.BaseRequest request) async { request.headers['user-agent'] = await ApiUtils.getUserAgent(); return await _inner.send(request); } } class MWApi { static Uri apiBaseUri = Uri.parse(Global.wikiApiUrl); static HttpClient getHttpClient() { return HttpClient(); } static Future> _getHeaders() async { var headers = { "X-IsekaiWikiApp-Version": Global.packageInfo?.version ?? "unknow", }; if (!kIsWeb) { headers["User-Agent"] = await ApiUtils.getUserAgent(); } return headers; } static Future>> get(String action, {Map? query}) async { Map queryStr = query?.map((key, value) => MapEntry(key, value.toString())) ?? {}; queryStr.addAll({ "action": action, "format": "json", "formatversion": "2", "uselang": Global.wikiLang, }); if (Global.webOrigin != null) { queryStr["origin"] = Global.webOrigin!; } Uri requestUri = apiBaseUri.replace(queryParameters: queryStr); var res = await http.get(requestUri, headers: await _getHeaders()); if (res.statusCode != 200) { throw HttpResponseCodeError(res.statusCode); } var responseBody = res.body; return parseMWResponse(action, responseBody); } static MWResponse> parseMWResponse(String action, String resJson) { var mwRes = MWResponse>(); List errorList = []; var resData = jsonDecode(resJson); if (resData is Map) { // 处理请求错误 var resError = resData["error"]; if (resError is Map) { errorList.add(MWError.fromMap(resError)); } else if (resError is List) { for (var errItem in resError) { if (errItem is Map) { errorList.add(MWError.fromMap(errItem)); } } } if (errorList.isNotEmpty) { mwRes.errorList = errorList; return mwRes; } // 请求结果 if (resData.containsKey(action) && resData[action] is Map) { mwRes.data = resData[action] as Map; mwRes.ok = true; } // 继续查询参数 var batchcomplete = resData["batchcomplete"]; if (batchcomplete is bool && batchcomplete) { var continueInfo = resData["continue"]; if (continueInfo is Map) { mwRes.continueInfo = {}; continueInfo.forEach((key, value) { var keyStr = key.toString(); mwRes.continueInfo![keyStr] = value.toString(); }); } } } return mwRes; } }