add book search

This commit is contained in:
wanxp 2022-06-16 20:51:36 +08:00
parent 382d79ec73
commit ee2dead393
8 changed files with 101 additions and 16 deletions

@ -24,9 +24,10 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
abstract support(extract: DoubanSubject): boolean;
handle(url:string, editor:Editor):void {
Promise.resolve().then(() => get(url + "/", {headers: JSON.parse(this.doubanPlugin.settings.searchHeaders)}))
Promise.resolve().then(() => get(log.traceN("GET URL", url + "/"), log.traceN("GET HEAD", {headers: JSON.parse(this.doubanPlugin.settings.searchHeaders)})))
.then(readStream)
.then(cheerio.load)
.then(log.trace)
.then(this.parseSubjectFromHtml)
.then(content => this.toEditor(editor, content))
// .then(content => content ? editor.replaceSelection(content) : content)

@ -0,0 +1,68 @@
import { Editor, moment, renderResults } from "obsidian";
import cheerio, { CheerioAPI } from 'cheerio';
import { get, readStream } from "tiny-network";
import DoubanAbstractLoadHandler from "./DoubanAbstractLoadHandler";
import DoubanBookSubject from "douban/model/DoubanBookSubject";
import DoubanPlugin from "main";
import { DoubanPluginSettings } from "douban/Douban";
import DoubanSubject from "douban/model/DoubanSubject";
import SchemaOrg from "utils/SchemaOrg";
import { log } from "utils/Logutil";
export default class DoubanBookLoadHandler extends DoubanAbstractLoadHandler<DoubanBookSubject> {
parseText(extract: DoubanBookSubject, settings:DoubanPluginSettings): string {
return settings.movieTemplate ? settings.movieTemplate.replaceAll("{{id}}", extract.id)
.replaceAll("{{type}}", extract.type ? extract.type : "")
.replaceAll("{{title}}", extract.title ? extract.title : "")
.replaceAll("{{desc}}", extract.desc ? extract.desc : "")
.replaceAll("{{image}}", extract.image ? extract.image : "")
// .replaceAll("{{director}}", extract.director ? extract.director.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
// .replaceAll("{{actor}}", extract.actor ? extract.actor.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
.replaceAll("{{author}}", extract.author ? extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
.replaceAll("{{datePublished}}", extract.datePublished ? moment(extract.datePublished).format(settings.dateFormat) : "")
.replaceAll("{{url}}", extract.url ? extract.url : "")
.replaceAll("{{score}}", extract.aggregateRating && extract.aggregateRating.ratingValue ? extract.aggregateRating.ratingValue + "" : "")
: undefined; }
support(extract: DoubanSubject): boolean {
return extract && extract.type && (extract.type.contains("书籍") || extract.type.contains("Book") || extract.type.contains("book"));
}
constructor(doubanPlugin:DoubanPlugin) {
super(doubanPlugin);
}
parseSubjectFromHtml(data: CheerioAPI): DoubanBookSubject {
return data('script')
.get()
.filter(scd => "application/ld+json" == data(scd).attr("type"))
.map(i => {
var item = data(i).text();
item = super.html_decode(item);
var obj = JSON.parse(item.replace(/[\r\n\s+]/g, ''));
var idPattern = /(\d){5,10}/g;
var id = idPattern.exec(obj.url);
const result:DoubanBookSubject = {
id: id?id[0]:'',
type: 'Book',
title: obj.name,
desc: obj.description,
url: "https://book.douban.com" + obj.url,
author: obj.author,
aggregateRating: obj.aggregateRating,
datePublished: obj.datePublished ? new Date(obj.datePublished) : undefined,
image:obj.image
}
return result;
})[0];
}
}

@ -7,7 +7,7 @@ import { DoubanPluginSettings } from "douban/Douban";
import DoubanSubject from "../model/DoubanSubject";
import DoubanSubjectLoadHandler from "./DoubanSubjectLoadHandler";
export class DoubanEtractHandler {
export class DoubanSearchChooseItemHandler {
private _app:App;
private _doubanPlugin:DoubanPlugin;
@ -32,10 +32,7 @@ export class DoubanEtractHandler {
var doubanSubjectHandlers:DoubanSubjectLoadHandler<DoubanSubject>[] = this._doubanSubjectHandlers
.filter(h => h.support(searchExtract));
if(doubanSubjectHandlers && doubanSubjectHandlers.length > 0) {
var result = doubanSubjectHandlers.map(h => h.handle(searchExtract.url, editor))
if(result && result.length > 0) {
return result[0];
}
doubanSubjectHandlers[0].handle(searchExtract.url, editor);
}else {
this._doubanSubjectHandlerDefault.handle(searchExtract.url, editor);
}

@ -0,0 +1,10 @@
import {AggregateRating, Person, WithContext} from 'schema-dts';
import DoubanSubject from "./DoubanSubject";
export default class DoubanMovieSubject extends DoubanSubject {
author:Person[];
aggregateRating:AggregateRating;
datePublished:Date;
image:string
}

@ -33,6 +33,7 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
}
onChooseItem(item: DoubanSearchResultSubject, evt: MouseEvent | KeyboardEvent): void {
log.trace(`you chosen : ${JSON.stringify(item)}`)
this.plugin.doubanEtractHandler.handle(item, this.editor);
}

@ -14,7 +14,7 @@ export default class Searcher {
// return Promise.resolve();
return Promise
.resolve()
.then(() => get(doubanSettings.searchUrl + searchItem, JSON.parse(doubanSettings.searchHeaders)))
.then(() => get(log.traceN("GET", doubanSettings.searchUrl + searchItem), JSON.parse(doubanSettings.searchHeaders)))
.then(ensureStatusCode(200))
.then(readStream)
.then(cheerio.load)

16
main.ts

@ -1,9 +1,9 @@
import { DEFAULT_SETTINGS, DoubanPluginSettings } from "./douban/Douban";
import { Editor, Plugin } from "obsidian";
import { DoubanEtractHandler } from "douban/handler/DoubanExtractHandler";
import { DoubanFuzzySuggester } from "douban/search/DoubanSearchFuzzySuggestModal";
import DoubanMovieSubject from "douban/model/DoubanMovieSubject";
import { DoubanSearchChooseItemHandler } from "douban/handler/DoubanSearchChooseItemHandler";
import { DoubanSearchModal } from "douban/search/DoubanSearchModal";
import { DoubanSettingTab } from "douban/DoubanSettingTab";
import DoubanSubject from "douban/model/DoubanSubject";
@ -13,12 +13,14 @@ import { log } from "utils/Logutil";
export default class DoubanPlugin extends Plugin {
public settings: DoubanPluginSettings;
public doubanEtractHandler: DoubanEtractHandler;
public doubanEtractHandler: DoubanSearchChooseItemHandler;
async putToEditor(editor:Editor, extract:DoubanSubject) {
if(!editor || !extract) {
log.trace(`chosen item can not load data`);
return;
}
log.trace(`you choose item load data success: ${JSON.stringify(extract)}`);
var content:string = this.doubanEtractHandler.parseText(extract, this.settings)
if(content) {
editor.replaceSelection(content);
@ -33,7 +35,7 @@ export default class DoubanPlugin extends Plugin {
new DoubanFuzzySuggester(this, editor).showSearchList(resultList);
}
async getDoubanMovieTextForActiveFile(editor: Editor) {
async getDoubanTextForActiveFile(editor: Editor) {
const activeFile = await this.app.workspace.getActiveFile();
if (activeFile) {
const searchTerm = activeFile.basename;
@ -43,7 +45,7 @@ export default class DoubanPlugin extends Plugin {
}
}
async geDoubanMovieTextForSearchTerm(editor: Editor) {
async geDoubanTextForSearchTerm(editor: Editor) {
new DoubanSearchModal(this.app, this, editor).open();
}
@ -54,7 +56,7 @@ export default class DoubanPlugin extends Plugin {
id: "search-douban-by-current-file-name",
name: i18nHelper.getMessage("search douban by current file name"),
editorCallback: (editor: Editor) =>
this.getDoubanMovieTextForActiveFile(editor),
this.getDoubanTextForActiveFile(editor),
});
@ -62,7 +64,7 @@ export default class DoubanPlugin extends Plugin {
id: "search-douban-and-input-current-file",
name: i18nHelper.getMessage("search douban and import to current file"),
editorCallback: (editor: Editor) =>
this.geDoubanMovieTextForSearchTerm(editor),
this.geDoubanTextForSearchTerm(editor),
});
this.addSettingTab(new DoubanSettingTab(this.app, this));
@ -70,7 +72,7 @@ export default class DoubanPlugin extends Plugin {
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
this.doubanEtractHandler = new DoubanEtractHandler(this.app, this);
this.doubanEtractHandler = new DoubanSearchChooseItemHandler(this.app, this);
}
async saveSettings() {

@ -19,9 +19,15 @@ class Logger {
}
public trace(e:any):any {
return e;
// console.log(`Douban Plugin trace: ${typeof e == 'string' ? e : JSON.stringify(e)}`);
// return e;
console.log(`Douban Plugin trace: ${typeof e == 'string' ? e : JSON.stringify(e)}`);
return e;
}
public traceN(notion:string, e:any):any {
// return e;
console.log(`${notion} ${typeof e == 'string' ? e : JSON.stringify(e)}`);
return e;
}
}