|
|
|
import 'package:isekai_wiki/api/mw/mw_api.dart';
|
|
|
|
import 'package:isekai_wiki/api/response/page_info.dart';
|
|
|
|
import 'package:isekai_wiki/api/response/recent_changes.dart';
|
|
|
|
|
|
|
|
class MWApiList {
|
|
|
|
/// 获取最近更改列表
|
|
|
|
static Future<MWResponse<List<RecentChangesItem>>> getRecentChanges(String type,
|
|
|
|
{int? limit, Map<String, String>? continueInfo}) async {
|
|
|
|
var query = {
|
|
|
|
"list": "recentchanges",
|
|
|
|
"rctype": type,
|
|
|
|
"rcnamespace": 0,
|
|
|
|
"rclimit": limit,
|
|
|
|
};
|
|
|
|
if (continueInfo != null && continueInfo.containsKey("rccontinue")) {
|
|
|
|
query["rccontinue"] = continueInfo["rccontinue"];
|
|
|
|
}
|
|
|
|
|
|
|
|
var mwRes = await MWApi.get("query", params: query);
|
|
|
|
var rcRes = RecentChangesResponse.fromJson(mwRes.data);
|
|
|
|
|
|
|
|
return mwRes.replaceData(rcRes.recentchanges);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 获取合并的最近更改列表(包括新页面和最近更新)
|
|
|
|
static Future<MWResponse<List<RecentChangesItem>>> getMixedRecentChanges(
|
|
|
|
{int? limit, Map<String, String>? continueInfo}) async {
|
|
|
|
Map<String, String> continueInfoNew = {};
|
|
|
|
Map<String, String> continueInfoEdit = {};
|
|
|
|
|
|
|
|
bool ignoreRcNew = false;
|
|
|
|
bool ignoreRcEdit = false;
|
|
|
|
|
|
|
|
if (continueInfo != null) {
|
|
|
|
ignoreRcNew = true;
|
|
|
|
ignoreRcEdit = true;
|
|
|
|
|
|
|
|
if (continueInfo.containsKey("rcnewcontinue")) {
|
|
|
|
continueInfoNew["rccontinue"] = continueInfo["rcnewcontinue"]!;
|
|
|
|
ignoreRcNew = false;
|
|
|
|
}
|
|
|
|
if (continueInfo.containsKey("rceditcontinue")) {
|
|
|
|
continueInfoEdit["rccontinue"] = continueInfo["rceditcontinue"]!;
|
|
|
|
ignoreRcEdit = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var rcResList = await Future.wait([
|
|
|
|
ignoreRcNew
|
|
|
|
? Future.value(MWResponse<List<RecentChangesItem>>([]))
|
|
|
|
: getRecentChanges("new", limit: limit, continueInfo: continueInfoNew),
|
|
|
|
ignoreRcEdit
|
|
|
|
? Future.value(MWResponse<List<RecentChangesItem>>([]))
|
|
|
|
: getRecentChanges("edit", limit: limit, continueInfo: continueInfoEdit),
|
|
|
|
]);
|
|
|
|
|
|
|
|
var rcNewRes = rcResList[0];
|
|
|
|
var rcEditRes = rcResList[1];
|
|
|
|
|
|
|
|
List<RecentChangesItem> mergedList = [...rcNewRes.data, ...rcEditRes.data];
|
|
|
|
|
|
|
|
mergedList.sort((a, b) {
|
|
|
|
// 为新页面添加7天的保护期
|
|
|
|
var timeA = a.type == "new" ? a.timestamp.add(const Duration(days: 7)) : a.timestamp;
|
|
|
|
var timeB = b.type == "new" ? b.timestamp.add(const Duration(days: 7)) : b.timestamp;
|
|
|
|
|
|
|
|
return timeB.compareTo(timeA);
|
|
|
|
});
|
|
|
|
|
|
|
|
List<RecentChangesItem> uniqueMergedList = [];
|
|
|
|
for (var page in mergedList) {
|
|
|
|
if (uniqueMergedList.indexWhere((element) => element.pageid == page.pageid) == -1) {
|
|
|
|
uniqueMergedList.add(page);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Map<String, String> mergedContinueInfo = {};
|
|
|
|
if (rcNewRes.continueInfo != null && rcNewRes.continueInfo!.containsKey("rccontinue")) {
|
|
|
|
mergedContinueInfo["rcnewcontinue"] = rcNewRes.continueInfo!["rccontinue"]!;
|
|
|
|
}
|
|
|
|
if (rcEditRes.continueInfo != null && rcEditRes.continueInfo!.containsKey("rccontinue")) {
|
|
|
|
mergedContinueInfo["rceditcontinue"] = rcEditRes.continueInfo!["rccontinue"]!;
|
|
|
|
}
|
|
|
|
|
|
|
|
return MWResponse(
|
|
|
|
uniqueMergedList,
|
|
|
|
continueInfo: mergedContinueInfo.isNotEmpty ? mergedContinueInfo : null,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Future<MWResponse<List<PageInfo>>> getPageInfoList(
|
|
|
|
{List<int>? pageids,
|
|
|
|
List<String>? titles,
|
|
|
|
List<String>? prop,
|
|
|
|
Map<String, dynamic>? extraParams,
|
|
|
|
bool getInWatchlist = false,
|
|
|
|
int extractChars = 200}) async {
|
|
|
|
prop ??= ["extracts", "info", "pageimages"];
|
|
|
|
|
|
|
|
Map<String, dynamic> query = {
|
|
|
|
"redirects": 1,
|
|
|
|
"converttitles": 1,
|
|
|
|
"exintro": 1,
|
|
|
|
"explaintext": 1,
|
|
|
|
"exchars": extractChars,
|
|
|
|
"inprop": "url",
|
|
|
|
"piprop": "thumbnail",
|
|
|
|
"pithumbsize": 640,
|
|
|
|
"pilicense": "any"
|
|
|
|
};
|
|
|
|
|
|
|
|
if (getInWatchlist) {
|
|
|
|
prop.add("inwatchlist");
|
|
|
|
}
|
|
|
|
query["prop"] = prop.join("|");
|
|
|
|
|
|
|
|
if (pageids != null) {
|
|
|
|
query["pageids"] = pageids.join("|");
|
|
|
|
}
|
|
|
|
if (titles != null) {
|
|
|
|
query["titles"] = titles.join("|");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (extraParams != null) {
|
|
|
|
query.addAll(extraParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
var mwRes = await MWApi.get("query", params: query);
|
|
|
|
|
|
|
|
var pagesRes = PagesResponse.fromJson(mwRes.data);
|
|
|
|
|
|
|
|
var pageList = pagesRes.pages.map((pageInfo) {
|
|
|
|
if (pageInfo.description != null) {
|
|
|
|
pageInfo.description = pageInfo.description!.replaceAll(RegExp(r"\n\n"), "\n");
|
|
|
|
}
|
|
|
|
if (pageInfo.title.contains("/")) {
|
|
|
|
var splitPos = pageInfo.title.lastIndexOf("/");
|
|
|
|
pageInfo.displayTitle = pageInfo.title.substring(splitPos + 1);
|
|
|
|
pageInfo.subtitle = pageInfo.title.substring(0, splitPos);
|
|
|
|
} else {
|
|
|
|
pageInfo.displayTitle = pageInfo.title;
|
|
|
|
}
|
|
|
|
return pageInfo;
|
|
|
|
}).toList();
|
|
|
|
// 按照传入顺序对页面进行排序
|
|
|
|
List<PageInfo> sortedPages = [];
|
|
|
|
|
|
|
|
if (pageids != null) {
|
|
|
|
for (var pageid in pageids) {
|
|
|
|
var index = pageList.indexWhere((element) => element.pageid == pageid);
|
|
|
|
if (index != -1) {
|
|
|
|
sortedPages.add(pageList[index]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (titles != null) {
|
|
|
|
for (var title in titles) {
|
|
|
|
var index = pagesRes.pages.indexWhere((element) => element.title == title);
|
|
|
|
if (index != -1) {
|
|
|
|
sortedPages.add(pagesRes.pages[index]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mwRes.replaceData(sortedPages);
|
|
|
|
}
|
|
|
|
}
|