mirror of
https://github.com/Wanxp/obsidian-douban.git
synced 2026-04-04 16:48:44 +08:00
在 parseVariable 方法中为所有数组字段的 .map() 调用添加 (field || []) 保护, 防止当字段为 undefined 时调用 .map() 报错。
159 lines
5.8 KiB
TypeScript
159 lines
5.8 KiB
TypeScript
import {CheerioAPI} from 'cheerio';
|
|
import DoubanAbstractLoadHandler from "./DoubanAbstractLoadHandler";
|
|
import DoubanPlugin from "../../../main";
|
|
import DoubanSubject from '../model/DoubanSubject';
|
|
import DoubanGameSubject from '../model/DoubanGameSubject';
|
|
import HandleContext from "../model/HandleContext";
|
|
import {DataValueType, PersonNameMode, SupportType} from "../../../constant/Constsant";
|
|
import {UserStateSubject} from "../model/UserStateSubject";
|
|
import {moment} from "obsidian";
|
|
import {TITLE_ALIASES_SPECIAL_CHAR_REG_G} from "../../../utils/YamlUtil";
|
|
import {DataField} from "../../../utils/model/DataField";
|
|
import {b} from "@shikijs/engine-javascript/dist/shared/engine-javascript.BnuFKbIS";
|
|
|
|
export default class DoubanGameLoadHandler extends DoubanAbstractLoadHandler<DoubanGameSubject> {
|
|
|
|
constructor(doubanPlugin: DoubanPlugin) {
|
|
super(doubanPlugin);
|
|
}
|
|
|
|
getSupportType(): SupportType {
|
|
return SupportType.game;
|
|
}
|
|
getHighQuantityImageUrl(fileName:string):string{
|
|
return `https://img9.doubanio.com/lpic/${fileName}`;
|
|
}
|
|
|
|
getSubjectUrl(id:string):string{
|
|
return `https://www.douban.com/game/${id}/`;
|
|
}
|
|
|
|
parseVariable(beforeContent: string, variableMap:Map<string, DataField>, extract: DoubanGameSubject, context: HandleContext): void {
|
|
// super.parseAliases(beforeContent, variableMap, extract, context);
|
|
variableMap.set("aliases", new DataField("aliases", DataValueType.array, extract.aliases,
|
|
(extract.aliases || []).map(a=>a
|
|
.trim()
|
|
// .replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')
|
|
// //replase multiple _ to single _
|
|
// .replace(/_+/g, '_')
|
|
// .replace(/^_/, '')
|
|
// .replace(/_$/, '')
|
|
.replace(/:\s+/g, ':')
|
|
)));
|
|
// super.parseAliases(beforeContent, variableMap, extract, context);
|
|
}
|
|
|
|
support(extract: DoubanSubject): boolean {
|
|
return extract && extract.type && (extract.type.contains("游戏") || extract.type.contains("Game") || extract.type.contains("game"));
|
|
}
|
|
|
|
analysisUser(html: CheerioAPI, context: HandleContext): {data:CheerioAPI , userState: UserStateSubject} {
|
|
let rate = html('input#n_rating').val();
|
|
const rating = html('span#rating');
|
|
const tagsStr = rating.parent().next().text().trim();
|
|
const tags = tagsStr ? tagsStr.replace('标签:', '').trim().split(' ') : null;
|
|
const collected = html('div.collection-section > div.collection-rating-stars > div.collection-collected');
|
|
const stateWord = collected.find('span.collection-result').text().trim();
|
|
const collectionDateStr = collected.find('span.color_gray').text().trim();
|
|
const userState1 = DoubanAbstractLoadHandler.getUserState(stateWord);
|
|
const component = rating.parent().next().next().text().trim();
|
|
|
|
const userState: UserStateSubject = {
|
|
tags: tags,
|
|
rate: rate?Number(rate):null,
|
|
state: userState1,
|
|
collectionDate: collectionDateStr?moment(collectionDateStr, 'YYYY-MM-DD').toDate():null,
|
|
comment: component
|
|
}
|
|
return {data: html, userState: userState};
|
|
}
|
|
|
|
parseSubjectFromHtml(html: CheerioAPI, context: HandleContext): DoubanGameSubject {
|
|
let title = html(html("#content > h1").get(0)).text();
|
|
title = this.getPersonNameByMode(title, PersonNameMode.CH_NAME);
|
|
let idContent = html(html("head > meta[name= 'mobile-agent']").get(0)).attr("content");
|
|
let idPattern = /(\d){5,10}/g;
|
|
let idP = idPattern.exec(idContent);
|
|
let id = idP ? idP[0] : "";
|
|
let score = html(html("#interest_sectl > div > div.rating_self.clearfix > strong[property= 'v:average']").get(0)).text();
|
|
let detailDom = html(html("dl.thing-attr").get(0));
|
|
let dt = detailDom.find("dt");
|
|
let image = html(html("#content > div > div.article > div.mod.item-subject > div.item-subject-info > div > a > img").get(0)).attr("src");
|
|
let desc = html(html("#link-report > p").get(0)).text();
|
|
|
|
let url = `https://www.douban.com/game/${id}/`;
|
|
let valueMap = new Map<string, any>();
|
|
let value: any;
|
|
dt.map((index, info) => {
|
|
let key = html(info).text().trim();
|
|
if (key.indexOf('平台') >= 0 || key.indexOf('类型') >= 0) {
|
|
value = [];
|
|
html(info.next.next).find("a").map((index, a) => {
|
|
value.push(html(a).text().trim());
|
|
});
|
|
} else if (key.indexOf('别名') >= 0) {
|
|
let cc = html(info.next.next).text().trim();
|
|
value = cc.split("/");
|
|
} else {
|
|
value = html(info.next.next).text().trim();
|
|
}
|
|
valueMap.set(GameKeyValueMap.get(key), value);
|
|
})
|
|
|
|
const result: DoubanGameSubject = {
|
|
id: id,
|
|
type: this.getSupportType(),
|
|
title: title,
|
|
desc: desc,
|
|
url: url,
|
|
genre: valueMap.has('genre') ? valueMap.get('genre') : [],
|
|
image: image,
|
|
imageUrl: image,
|
|
datePublished: valueMap.has('datePublished') ? new Date(valueMap.get('datePublished')) : undefined,
|
|
publisher: valueMap.has('publisher') ? valueMap.get('publisher') : "",
|
|
score: Number(score),
|
|
aliases: valueMap.has('aliases') ? valueMap.get('aliases') : [],
|
|
developer: valueMap.has('developer') ? valueMap.get('developer') : "",
|
|
platform: valueMap.has('platform') ? valueMap.get('platform') : []
|
|
};
|
|
return result
|
|
}
|
|
|
|
//TODO support game's name i18n
|
|
// handleI18nName(title: string, settings: DoubanPluginSettings):string {
|
|
// if (!title) {
|
|
// return "";
|
|
// }
|
|
// if (!settings) {
|
|
// return title;
|
|
// }
|
|
// let resultName:string = "";
|
|
// let regValue:RegExpExecArray;
|
|
// switch(settings.personNameMode) {
|
|
// case PersonNameMode.CH_NAME:
|
|
// regValue = /[\u4e00-\u9fa5]{2,20}/g.exec(title);
|
|
// resultName = regValue?regValue[0]:title;
|
|
// break;
|
|
// case PersonNameMode.EN_NAME:
|
|
// regValue = /[a-zA-Z.\s\-]{2,50}/g.exec(title);
|
|
// resultName = regValue?regValue[0]:title;
|
|
// break;
|
|
// default:
|
|
// resultName = title;
|
|
// }
|
|
// return resultName;
|
|
// }
|
|
|
|
}
|
|
|
|
const GameKeyValueMap: Map<string, string> = new Map(
|
|
[['类型:', 'genre'],
|
|
['平台:', 'platform'],
|
|
['别名:', 'aliases'],
|
|
['开发商:', 'developer'],
|
|
['发行商:', 'publisher'],
|
|
['发行日期:', 'datePublished'],
|
|
]
|
|
);
|
|
|