You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
3.9 KiB
Dart

2 years ago
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';
2 years ago
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<MWError> errorList;
MWMultiError(this.errorList);
@override
String toString() {
return errorList.map((e) => e.info).join("\n");
}
}
class MWResponse<T> {
bool ok = false;
List<MWError>? errorList;
T? data;
Map<String, String>? continueInfo;
MWResponse({this.ok = false, this.errorList, this.data, this.continueInfo});
}
class MWApiClient extends http.BaseClient {
final http.Client _inner;
MWApiClient(this._inner);
Future<http.StreamedResponse> 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);
2 years ago
static HttpClient getHttpClient() {
return HttpClient();
}
static Future<Map<String, String>> _getHeaders() async {
var headers = {
"X-IsekaiWikiApp-Version": Global.packageInfo?.version ?? "unknow",
};
if (!kIsWeb) {
headers["User-Agent"] = await ApiUtils.getUserAgent();
}
return headers;
}
static Future<MWResponse<Map<String, dynamic>>> get(String action,
{Map<String, dynamic>? query}) async {
Map<String, String> 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<Map<String, dynamic>> parseMWResponse(String action, String resJson) {
var mwRes = MWResponse<Map<String, dynamic>>();
List<MWError> 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<String, dynamic>;
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;
}
}